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.
- You can use default to define normal methods that need to be called by objects.
- 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:
- Common execution thread pool definition: Interface ExecutorService
- 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.