Basic Java Learning 13 Lambda and Introduction to thread pools

“This is the 13th day of my participation in the November Gwen Challenge. See details: The Last Gwen Challenge 2021”.

About the author

  • The authors introduce

🍓 Blog home page: author’s home page 🍓 Introduction: 🥇, a high quality creator in JAVA field, 🎓, a junior in college, participated in various provincial and national competitions and won a series of honors. 🍓 pay attention to me: pay attention to my learning materials, document download all have, regularly update the article every day, inspirational to do a JAVA senior program ape 👨💻.


Interface Definition Enhancement

The core problem with this awkward situation is that the interface is just a declaration of a method, not a method implementation, so over time, if any of the above problems occur, the interface will no longer be used. To solve this problem, two specialized interfaces are available from JDK1.8.

  1. You can use default to define normal methods that need to be called by objects.
  2. You can use static to define static methods, using the interface name.

Defining common methods

package com.annotation;
interface IMess{
	public default void fun(a){// Append the normal method to the method body
		System.out.println("hello,world!");
	}
	public void print(a);
}
class MessImpl implements IMess{

	@Override
	public void print(a) {
		// TODO Auto-generated method stub
		System.out.println("www.baidu.com"); }}public class Demo3 {
	public static void main(String[] args) {
		MessImpl msg = newMessImpl(); msg.print(); msg.fun(); }}Copy the code

Define static methods

package com.annotation;
interface IMess{
	public default void fun(a){// Append the normal method to the method body
		System.out.println("hello,world!");
	}
	public static IMess getInstance(a){// Define static methods
		return new MessImpl();
	}
	public void print(a);
}
class MessImpl implements IMess{

	@Override
	public void print(a) {
		// TODO Auto-generated method stub
		System.out.println("www.baidu.com"); }}public class Demo3 {
	public static void main(String[] args) {
// MessImpl msg = new MessImpl();IMess msg = IMess.getInstance(); msg.print(); msg.fun(); }}Copy the code

On the whole, interfaces are more like abstract classes, but more powerful than abstract classes in that subclasses of interfaces can still implement multiple inheritance relationships, while abstract classes remain single inheritance.

Lambda expressions

The most representative one is Haskell. Functional programming and object-oriented programming are two major development camps

Traditional object-oriented development

package com.annotation;
interface IMess{
	public void print(a);
}
public class Demo3 {
	public static void main(String[] args) {
		IMess msg = new IMess(){
			public void print(a){
				System.out.println("Hello,world!"); }; }; msg.print(); }}Copy the code

The biggest advantage of using anonymous inner classes to implement interfaces is that they save a file, but the biggest disadvantage is that they are too confusing to look at. If you use a functional programming model.

Functional programming model

package com.annotation;
interface IMess{
	public void print(a);
}
public class Demo3 {
	public static void main(String[] args) {
		IMess msg = ()->System.out.println("Hello,world!"); msg.print(); }}Copy the code

If you want to use the functional programming premise, the interface can write only one method, and if you write two methods, you get a syntax error. You can declare this to be a FunctionalInterface by prefacing it with @functionalinterface.

In fact, for the above grammatical forms:

  • (Parameter)-> Single line statement;

The method itself contains only one line of statements, so we can write the statement directly. If there are multiple lines of statements, we need to use “{}”.

package com.annotation;
@FunctionalInterface
interface IMess{
	public void print(a);
}
public class Demo3 {
	public static void main(String[] args) {
		IMess msg = ()->{
			System.out.println("Hello,world!");
			System.out.println("Hello,world!");
			System.out.println("Hello,world!"); }; msg.print(); }}Copy the code

If all you have in your expression is a single line that returns data, use statements instead of return.

package com.annotation;
interface IMath{
	public int add(int x, int y);
}
public class Demo4 {
	public static void main(String[] args) {
		IMath msg = (p1, p2)-> p1 + p2;
		System.out.println(msg.add(10.20)); }}Copy the code

The thread pool

Thread pooling is the operation of multiple threads wrapped together.

Thread pool concept

We often meet each other in life. Today it takes 20 people to develop a project

  • It’s a big job. We need as many people as possible

  • It’s a big job, but it requires 10 people

  • It’s a big job, but it only requires one person to do it

Append a concurrent access protocol: java.util.concurrent, where the core classes and interfaces for the operations on this thread pool are defined. There are two core interfaces:

  1. Common execution thread pool definition: Interface ExecutorService
  2. Scheduling thread pool: Interface ScheduledExecutorService

Use the Class Executors Class to create a thread pool

  • ExecutorService newCachedThreadPool() Public static ExecutorService newCachedThreadPool()
  • Create a fixed-size thread pool: public static ExecutorService newFixedThreadPool(int nThreads)
  • Public static ExecutorService newSingleThreadExecutor()
  • Public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

Implementation of thread pools

Create a thread pool of unlimited size

package com.day13.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class PoolDemo1 {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		// create a thread pool model, but there are no threads behind it
		ExecutorService executorService = Executors.newCachedThreadPool();
		for (int i = 0; i < 10; i++) {
			int index = i;
			Thread.sleep(200);
			executorService.submit(()-> {
				System.out.println(Thread.currentThread().getName() + ",i = "+ index); }); } executorService.shutdown(); }}Copy the code

Create a thread pool of fixed size

package com.day13.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class PoolDemo1 {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		// create a thread pool model, but there are no threads behind it
		ExecutorService executorService = Executors.newFixedThreadPool(3);
		for (int i = 0; i < 10; i++) {
			int index = i;
			Thread.sleep(200);
			executorService.submit(()-> {
				System.out.println(Thread.currentThread().getName() + ",i = "+ index); }); } executorService.shutdown(); }}Copy the code

Create our single-threaded thread pool

package com.day13.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class PoolDemo1 {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		// create a thread pool model, but there are no threads behind it
		ExecutorService executorService = Executors.newSingleThreadExecutor();
		for (int i = 0; i < 10; i++) {
			int index = i;
			executorService.submit(()-> {
				System.out.println(Thread.currentThread().getName() + ",i = "+ index); }); } executorService.shutdown(); }}Copy the code

Scheduling pool

package com.day13.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class PoolDemo1 {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		// create a schedule pool with three thread sizes
		ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
		for (int i = 0; i < 10; i++) {
			//Thread.sleep(200);
			int index = i;
			executorService.scheduleAtFixedRate(new Runnable(){
				@Override
				public void run(a) {
					// TODO Auto-generated method stub
						System.out.println(Thread.currentThread().getName() + ",i = "+ index); }},3.2, TimeUnit.SECONDS);// The unit of one second is used, indicating that the execution will start after 3 seconds and then every 2 seconds}}}Copy the code

The only benefit that thread pooling brings to us as developers is that it allows multiple threads to process programs in a group mode, which is a great performance boost in a very complex business logic.

StringBuffer class

For class library learning, it is impossible to learn all. All you need to know is how to face the solution. Learn to query documents.

The StringBuffer class starts with a brief review of the characteristics of the String class:

String class, there are two kinds of objects instantiated way is a direct assignment, will only create a heap memory space, and the object can be automatically into the pool, another way to use constructor complete, two pieces of space will be opened, there was a space will be known as spam, and will not automatically into the pool, but can be by intern () method by hand into the pool;

String on once declared can not be changed, and the string object can be changed, but the change is its memory address to point to;

It is clear from the above that the String class is the most used class for representing strings, but it is not suitable for String operations that are frequently modified. In this case, the StringBuffer class is often used: The StringBuffer class makes it easy to modify, using the “+” in the String class to connect to the database, and the append() method to connect to the data.

With the StringBuffer operation, the contents of the StringBuffer can change.

package com.day13.demo;

public class BufferDemo {
	public static void main(String[] args) {
		StringBuffer buf = new StringBuffer();
		buf.append("hello").append(",world!");
		fun(buf);// Modify the buF content
		System.out.println(buf);
	}
	public static void fun(StringBuffer tem){
		tem.append("\n").append("zsr"); }}Copy the code

The main difference between a String and a StringBuffer is that the contents of a String cannot be modified, whereas the contents of a StringBuffer can be modified. However, the development choice is to choose the String class first.

Now we have two classes that operate on strings: String and StringBuffer. Let’s look at the relationship between these two classes:

The String class: StringBuffer class:
public final class String

extends Object

implements Serializable,Comparable,CharSequence
public final class StringBuffer

extends Object

implements Serializable, CharSequence

Both classes are subclasses of the “CharSequence” interface. This interface describes the character set, so strings are subclasses of the character set, and the easiest way to think of CharSequence is strings. But there’s one small thing to note: String and StringBuffer can’t be converted directly.

Use StringBuffer: Use the StringBuffer constructor, append() method

Change String to StringBuffer

Public StringBuffer(String STR)

package com.day13.demo;

public class BufferTest{
	public static void main(String[] args) throws Exception {
		String str = "Hello World.";
		StringBuffer buf = new StringBuffer(str);
		fun(buf);
		System.out.println(buf);
}
	private static void fun(StringBuffer temp) {
		temp.append("\n").append("zsr"); }}Copy the code

2. Use the Append () method of the StringBuffer class

package com.day13.demo;

public class BufferTest{
	public static void main(String[] args) throws Exception {
		String str = "Hello World.";
		StringBuffer buf = new StringBuffer();
		buf.append(str);
		fun(buf);
		System.out.println(sb);
	}
	private static void fun(StringBuffer temp) {
		temp.append("\n").append("zsr"); }}Copy the code

Turning StringBuffer into String is done using the toString() method of the StringBuffer class

package com.day13.demo;

public class BufferTest{
	public static void main(String[] args) throws Exception {
		StringBuffer buf = new StringBuffer("hello,World!"); String str = buf.toString(); System.out.println(str); }}Copy the code

In fact, StringBuffer has some features that String doesn’t have.

Public StringBuffer Reverse ()

package com.day13.demo;

public class BufferTest{
	public static void main(String[] args) throws Exception {
		StringBuffer buf = new StringBuffer("hello,World!"); System.out.println(buf.reverse()); }}Copy the code

Public StringBuffer delete(int start, int end)

package com.day13.demo;

public class BufferDemo {
	public static void main(String[] args) {
		StringBuffer buf = new StringBuffer("Hello,World!");
		System.out.println(buf.delete(5.11)); }}Copy the code

Public StringBuffer insert(int offset, Object obj)

package com.day13.demo;

public class BufferDemo {
	public static void main(String[] args) {
		StringBuffer buf = new StringBuffer("Hello,World!");
		System.out.println(buf.delete(5.11).insert(0."Hello,")); }}Copy the code

Q: What is the difference between String, StringBuffer, and StringBuilder?

  • The contents of strings cannot be modified. The contents of StringBuffer and StringBuilder can be modified
  • A StringBuffer with synchronous handling is a thread-safe operation, and a StringBuilder with asynchronous handling is a thread-unsafe operation.

The Runtime class

In every JVM process, there is a Runtime action class object of the type Runtime class. When I open up the documentation for this class, I find that there is no constructor definition in this class, but as WE learned before, every class has at least one constructor, and the constructor of this class actually exists but is not seen externally, because the constructor is privatized. This is a standard singleton design pattern. Public static Runtime getRuntime(); public static Runtime getRuntime();

The Runtime class allows you to view current memory operations:

Method names type describe
public long freeMemory() ordinary Gets the current free memory size
public long totalMemory() ordinary Gets the total space currently available
public long maxMemory() ordinary Get the size of the maximum available memory space
public native void gc() ordinary Perform garbage collection

Observe the retrieval of memory information

package com.day13.demo;

public class RuntimeDemo {
	public static void main(String[] args) {
		Runtime run = Runtime.getRuntime();
		System.out.println("1, MAX =" + byteToM(run.maxMemory()));
		System.out.println("1, the TOTAL =" +  byteToM(run.totalMemory()));
		System.out.println("1, FREE =" +  byteToM(run.freeMemory()));
	}
	public static double byteToM(long num){
		return (double) num / 1024 / 1024; }}Copy the code

Gc garbage collection

package com.day13.demo;

public class RuntimeDemo {
	public static void main(String[] args) {
		Runtime run = Runtime.getRuntime();
		System.out.println("1, MAX =" + byteToM(run.maxMemory()));
		System.out.println("1, the TOTAL =" +  byteToM(run.totalMemory()));
		System.out.println("1, FREE =" +  byteToM(run.freeMemory()));
		String str = "";
		for (int i = 0; i < 2222; i++) {
			str += i;
		}
		System.out.println("2, MAX =" + byteToM(run.maxMemory()));
		System.out.println("2, TOTAL =" +  byteToM(run.totalMemory()));
		System.out.println("2, FREE =" +  byteToM(run.freeMemory()));
		run.gc();// Garbage collection
		System.out.println("3, MAX =" + byteToM(run.maxMemory()));
		System.out.println("3, TOTAL =" +  byteToM(run.totalMemory()));
		System.out.println("3, FREE =" +  byteToM(run.freeMemory()));
	}
	public static double byteToM(long num){
		return (double) num / 1024 / 1024; }}Copy the code

Interview question: What is GC? How to deal with

  • Garbage Conllector (GC) : A Garbage collector used to free unwanted memory space
  • There are two forms of GC processing, either automatic and irregular invocation, or manual invocation using the Runtime’s GC () method.

The System class

Public static void arrayCopy (Object SRC,int srcPos,Object Dest,int destPos,int length) public static void arrayCopy (Object SRC,int srcPos,Object Dest,int destPos,int length)

Public static Long currentTimeMillis(); public static Long currentTimeMillis(); ** This method is used to obtain the time spent by an operation.

Observe the use of currentTimeMillis()

package com.day13.demo;

public class SystemDemo {
	public static void main(String[] args) {
		long start = System.currentTimeMillis();
		String str = "";
		for (int i = 0; i < 2222; i++) {
			str += i;
		}
		long end = System.currentTimeMillis();
		System.out.println("Take time:" + (end - start) + "ms"); }}Copy the code

Public static void gc(); public static void gc(); public static void gc();

We have emphasized the concept that a class object must be created using a constructor, so if an object does not use a constructor, it should be released, and when it is released, it should have a method to support it. So to do that, we can have a class that overrides the Finalize () method in Object. This method is defined by the Object class: protected void Finalize () throws Throwable. Exceptions or errors may occur before object collection, but even if they do occur, the program execution will not be affected, that is, the program execution will not be interrupted because of exceptions.

The Finalize () method is used

package com.day13.demo;
class Person{
	public Person(a){
		System.out.println("Ask, doll, come out!");
	}

	@Override
	protected void finalize(a) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("I'm going to hell, I'm not going to be human in my next life --");
		throw new Exception("Continue to live for thousands of years."); }}public class FinalizeDemo {
	public static void main(String[] args) {
		Person person = new Person();
		person = null;
		System.out.println("Has been reincarnated as a human being."); System.gc(); }}Copy the code

Interview question: Please explain the difference between final, finally and Finalize?

  • Final is a keyword used to define a parent class that cannot be inherited, a constant that cannot be overridden
  • Finally is a unified outlet for exception handling
  • Finalize is a method in the Object class that is called before objects are collected

Object cloning

Cloning is the concept of object replication, but this concept is rarely used because few people copy existing objects. The Object class itself supports Object cloning. Can be found that protected Object clone () throws CloneNotSupportedException; If we want to achieve cloning, then not all the objects of the class can be randomly cloned, the class of the object to be cloned must implement Cloneable interface, and the most important is that the interface does not have any abstract method, so the interface is only a identification interface, indicating a kind of ability.

Object cloning implementation

package com.day13.demo;
class Per implements Cloneable{// This interface must be implemented
	private String name;
	private int age;
	public Per(String name, int age) {
		super(a);this.name = name;
		this.age = age;
	}
	public String getName(a) {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge(a) {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString(a) {
		return "Per [name=" + name + ", age=" + age + "]";
	}
	@Override
	// Extend override permission protected to public
	public Object clone(a) throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();// The parent class is responsible for cloning}}public class CloneDemo {
	public static void main(String[] args) throws Exception{
		 Per perA = new Per("kaco".12);
		 //perA.clone(); The reason you can't write here is because this method is protected and you can only implement it in subclasses of different packages
		 Per perB = (Per) perA.clone();
		 perB.setAge(100); System.out.println(perA); System.out.println(perB); }}Copy the code

It is not meaningful. It needs to clearly indicate the function of the interface, which represents a capability.