Java multi-threaded collaboration and sharing between base & thread

Java Concurrency basis

Thread Foundation Classes

Java to create a thread in three ways:

  1. Through inheritance Thread class.
  2. By implementing Runnable interface.
  3. Create a thread through Callable and Future.
public class NewThread {

	//runnable接口实现类
    private static class UseRunnable implements Runnable{
        @Override
        public void run() {//线程方法执行体
            System.out.println("I am a runnable interface!");
        }
    }
	//callable接口实现类
    private static class UseCallable implements Callable<String>{
        @Override
        public String call() {//线程方法执行体
            System.out.println("I am a callable interface!");
            return "callable";
        }
    }
	//Thread类子类
    private static class UseThread extends Thread{
        @Override
        public void run() {
            System.out.println("I am extends Thread!");
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        UseRunnable useRunnable = new UseRunnable();
        new Thread(useRunnable).start();//声明一个Thread实例,然后将runnable接口实例传入构造方法,调用start方法,即可执行线程

        UseCallable useCallable = new UseCallable();//同runnable接口一样,new一个实例对象
        FutureTask<String> stringFutureTask = new FutureTask<>(useCallable);//因为callable接口是有返回值的,所以用FutureTask对象包装一下callable对象
        new Thread(stringFutureTask).start();//然后将futuretask对象传入
        System.out.println(stringFutureTask.get());//get方法是阻塞的

        Thread useThread = new UseThread();
        useThread.start();
    }
}

The step of using three methods

Step is performed by using a subclass inherits class Thread

  1. The direct successor Thread class and override the run () method, run () method as a thread of execution.
  2. Create an instance of the subclass and call the start () method, you can start the child thread.

The step of using the interface runnable

  1. Create runnable interface class, and implements run () method, the method will run as a thread of execution, no return value.
  2. Create an instance of runnable implementation class, which is created as a target Thread object, call the start method to start a new thread

callable interface steps:

  1. Create callable interface class, and implements call () method, this method will call a thread of execution, and return values.
  2. Create an instance of the implementation class callable using FutureTask packaging callable class object, which object encapsulates FutureTask callable object method call returns a value.
  3. Use FutureTask Thread object as a target object to create and start a new thread.
  4. Call FutureTask object get () method to capture the return value after the end of the sub-thread execution.

Runnable and Callable the difference?

Runnable and Callable on the basic functions are similar, just call Callable interface () method returns a value, so when using an object Callable need to use FutureTask again Callable object packaged, then passed to the Thread object the return value can be obtained call () by FutureTask.get () method method.

Why java provides a Thread class and offers two interfaces to achieve multi-threaded?

Because java is single inheritance, but can be more realized.

Then thread a little more about

Common threads api

  • void setDaemon (boolean on) mark this thread as a daemon thread or a user thread.
  • long getId (): Gets the identifier of the thread
  • String getName (): Gets the name of the thread
  • void setName (Sting name): Set the name of the thread
  • boolean isAlive (): Tests if this thread is active
  • void setPriority (int newPriority): set the priority level of high priority will be larger probability grab CPU time slice of the thread]
  • void join () / join (long millis) wait for the specified thread death / death or wait for the specified thread after a specified number of milliseconds
  • State Thread.State getState () to get the thread of the moment
  • static void yield () thread concessions

Thread priority

Each thread has a priority in Java.
By default, a thread inherits the priority of its parent thread.
Available the setPriority () method sets the priority of the thread, the thread priority of the Java 1-10, i.e. MIN_PRIORITY (1) - MAX_PRIORITY (10 ). NORM_PRIORITY (5).

  • Whenever a thread scheduler have the opportunity to choose a new thread, it will first have to select a higher priority thread.
  • But the thread priority is highly dependent on the system, under normal circumstances do not rely on thread priority.

Daemon thread

Java has two classes of threads: User Thread (user threads), Daemon Thread (daemon thread)

With a more mundane example, any guardian of a nanny entire JVM thread are all non-daemon threads:

As long as the current instance of the JVM does not end in any surviving a non-threaded daemon, a daemon thread on the work of all; only when the end of the last non-daemon thread, daemon threads with JVM with the end of the work.
Daemon's role is to provide convenient services to run other threads, daemon thread most typical application is the GC (garbage collector), it is a very competent guardian.

Both User and Daemon almost no difference, the only difference is in the fact that the virtual machine to leave: If User Thread have all been out of operation, leaving Daemon Thread exist, the virtual machine will quit. Because there was not to be the guardian, Daemon there is no work to do, and there is no need to continue running the program.

  • Can (Boolean) method provided by the thread as a daemon thread thread.setDaemon.
  • Is a daemon thread to pass thread.isDaemon () method to determine the thread.

Here are a few points to note:

  1. thread.setDaemon (true) must () before setting the thread.start, otherwise it will run out of a IllegalThreadStateException exception. You can not set up regular running thread as a daemon thread.
  2. New thread produced in the Daemon thread is the Daemon.
  3. Do not think that all applications can be assigned to service to Daemon, such as read and write operations or computational logic.
  4. Low priority, mainly to provide services to other objects in the system.

How to make thread stops working

Thread the natural termination of ways:

  • Natural thread execution is completed, it will automatically release the resource after the execution is complete.
  • After the process thread execution thrown an unhandled exception, an exception is thrown, the thread is automatically stopped, and release resources.

Java is not the recommended way to use

  • stop () method used to terminate a thread of execution, causes the thread will not release the right resources, is usually not given the opportunity thread to release resources that will be killed off.
  • suspend () method is used to suspend the implementation of the thread, easily lead to deadlocks, because the thread is still in possession of the resources in pause mode, which can lead to other needs of the resource thread waits for the thread loops, resulting in deadlock .
  • resume () method, execution threads for recovery, needs and suspend () method used in pairs, because the suspended thread needs to perform a recovery method to continue.

interrupt interrupt

  • void interrupt () method to interrupt a thread, not really interrupt (closed) this thread, but simply a property in this thread (interrupt flag) is set to true, the thread is interrupted, the decision by the thread itself.
  • boolean isInterrupted () method to determine whether the current thread in a broken state.
  • static boolean interrupted () method to determine whether the thread is in the interrupt status and interrupt bit to false.

After the interrupt mode there is a little problem, the thread is in the process of implementation may throw InterruptedException, but throws this exception, the thread interrupt flag will be reset to false, if you do need interrupt thread, requiring ourselves in a catch statement block in calling interrupt again () method, the interrupt flag is set to true, and now look at this example.

    private static class TestInterruptException implements Runnable{
        @Override
        public void run() {
            String threadName = Thread.currentThread().getName();
            while (!Thread.currentThread().isInterrupted()){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    System.out.println(threadName + "捕获到InterruptedException异常" + Thread.currentThread().isInterrupted());
                    e.printStackTrace();
//                    Thread.currentThread().interrupt();//中断请求
                }
                System.out.println("没有被中断!!!");
            }
            System.out.println("中断成功!!!");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        TestInterruptException useRunnable = new TestInterruptException();
        Thread thread = new Thread(useRunnable);
        thread.start();//开启线程
        Thread.sleep(500);//制造InterruptedException异常
        thread.interrupt();//中断请求
    }
没有被中断!!!
Thread-0捕获到InterruptedException异常false
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.kk.线程基础.HasInterruptExcption$TestInterruptException.run(HasInterruptExcption.java:17)
	at java.lang.Thread.run(Thread.java:748)
没有被中断!!!
没有被中断!!!
没有被中断!!!

We deliberately created a InterruptedException exception, and then find a thread has not been interrupted, so it will run forever, until the next interrupt request by printing the results.
Now we will catch the inside of the open comment. Then run it again.

没有被中断!!!
Thread-0捕获到InterruptedException异常false
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.kk.线程基础.HasInterruptExcption$TestInterruptException.run(HasInterruptExcption.java:17)
	at java.lang.Thread.run(Thread.java:748)
没有被中断!!!
中断成功!!!

The results can be seen from the print interrupt request is successful, the thread execution is completed.

Then InterruptedException anomaly is how to generate it?

  • When a thread A by calling threadB.interrupt () B interrupt thread, that thread B if a low-level interruptible blocking method in execution, such as Thread.sleep (), Thread.join () or Object.wait (), then it the unblocked and throw InterruptedException.

Shared between threads

Built-synchronized lock

The solution is synchronized keyword to access resources between multiple threads synchronization, synchronized keyword it can be modified to ensure that the code block or method at any time, only one thread of execution.

There are three ways of synchronized

Modified Examples of the method: the current applied to the object instance, before entering the code to obtain the current instance of the object lock.
public synchronized void test(){ // TODO }
Modified static method: that is to lock the current class will be applied to all instances of an object class.
public static synchronized void test(){ // TODO }
Modified block: designated lock object, before entering the code block to obtain a lock for a given object
synchronized (Test.class) { // TODO }

Object lock: Lock the current object, which can only be used to a thread, if a thread calls a synchronization method of this object, then the other threads have to wait to get a thread synchronization object can call other objects of the object after release method. Asynchronous method is not affected.

  • synchronized instance method modification
  • this synchronized code block incoming

Locks: Class object that is locked, the Class object for each class in the virtual machine has only one species, all the instance objects on this Class. So there is only one class lock.

  • synchronized modification of static methods
  • Class objects synchronized code block incoming

volatile keyword

To introduce a few basic concepts
  1. Reordering: reordering means operating instructions to improve the performance, at compile time or run on the instruction execution order adjusting mechanism. Reordering compiled into the reordering reordering and runtime. Reordering means compiler compiler analyzes the execution code in order to compile the source code, the source code to adjust the execution order on the premise that follow the principle of the as-if-serial. as-if-serial principle means that in a single-threaded environment, no matter how the execution result of the reordering, the code is determined. Runtime reordering means to improve the speed of execution, the instruction execution order of the system to perform the machine is adjusted.
  2. Visibility: Visibility memory means visibility between threads, modifying the state of a thread to another thread is visible, in simple words, if a thread is a modified A shared variable after the flag, the thread B to read, will be able to read the latest modification of the flag.
Current issues in Java Memory Model

Before JDK1.2, Java memory model implementation (ie, shared memory) reading of variables does not require special attention. In the current Java memory model, each thread can be stored in a variable copy their work memory, instead of reading and writing directly in main memory, which can not guarantee the visibility of the data.
Here Insert Picture Description

And the role of the volatile keyword usage

Usage: volatile variables can only be used to modify the methods and code blocks can not be modified.
effect:

  • With volatile variables, which also indicates the JVM, this variable is unstable, every time it passes through main memory.
  • To ensure the visibility of variables, reordering of instructions prevented. But it does not guarantee atomic variables.
You can use the volatile situation
  • This field does not follow the same style of other fields.
  • Write to the field does not depend on the current value.
  • No thread in violation of the expected semantic write an illegal value.
  • A read operation does not depend on the value of other non-volatile field.

When only one thread can modify the value of a field, other threads can freely read, then the field is declared as volatile is reasonable.

synchronized and volatile difference
  1. The volatile keyword lightweight thread synchronization is achieved, the volatile performance is certainly better than the synchronized keyword. But the volatile keyword can only be used for variables can be modified method synchronized keyword and code blocks. Efficiency has been significantly improved after the synchronized keyword conducted mainly in order to reduce to obtain and release locks bring the performance overhead introduced by biased locking and lightweight locks and other various optimization after JavaSE1.6, the actual development use the keyword synchronized scenes or more.
  2. Multithreaded access to the volatile keyword blocking will not occur, and may block the synchronized keyword occur
  3. to ensure the visibility of the volatile keyword data, but can not guarantee the atomicity of data. Both the synchronized keyword can be guaranteed.
  4. The volatile keyword is mainly used to solve the visibility of variables between multiple threads, and the synchronized keyword is solved resources between multiple threads to access synchronization.

ThreadLocal 类

ThreadLocal thread is a local copy of the variable tools. Mainly for the private copy of the object stored in the thread and the thread to do a mapping, variable between individual threads without disturbing each other, in a highly concurrent scenarios can be achieved without state calls, especially for dependent variable values ​​each thread does not make sense complete scenes operations.

ThreadLocal api
  • get () method is used to obtain a copy of the variable value of the current thread.
  • set () method to save a copy of the variable value of the current thread.
  • initialValue () value for the current thread initial copy of the variable.
  • remove () method removes the current copy of the variable value of the future.
    The following look at an example to show you the use of ThreadLocal
static ThreadLocal<Integer> threadLaocl = new ThreadLocal<Integer>(){
		@Override
		protected Integer initialValue() {
			return 1;
		}
	};

    /**
     *类说明:测试线程,线程的工作是将ThreadLocal变量的值变化,并写回,看看线程之间是否会互相影响
     */
    public static class TestThread implements Runnable{
        int id;
        public TestThread(int id){
            this.id = id;
        }
        public void run() {
            System.out.println(Thread.currentThread().getName()+":start");
            Integer s = threadLaocl.get();//获得变量的值
            s = s+id;
            threadLaocl.set(s);
            System.out.println(Thread.currentThread().getName()+":"
            +threadLaocl.get());
            //threadLaocl.remove();
        }
    }

    public static void main(String[] args){
	    //启动三个线程
        Thread[] runs = new Thread[3];
        for(int i=0;i<runs.length;i++){
            runs[i]=new Thread(new TestThread(i));//将i传入
        }
        for(int i=0;i<runs.length;i++){
            runs[i].start();
        }
    }

First contact, first look, to be later in-depth analysis.

Collaboration between threads

Life cycle and state of the thread

This segment is derived from

  • https://snailclimb.top/JavaGuide/#/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary
  • https://blog.csdn.net/pange1991/article/details/53860651

Java threads running at a given moment in the life cycle may only be in the following six different states of one state (Figure source "Java Concurrent Programming Art" section 4.1.4)

Here Insert Picture Description

In the life cycle of the thread is not fixed in one state, but with the execution of the code to switch between different states. Java thread a state transition as shown below (FIG source "Concurrent Programming Java Art" Section 4.1.4):
Here Insert Picture Description

Goes above may be looking a bit confusing, here this is to switch between the various states Lite Description (Figure source "Java core technology Volume" section 14.3.4)
Here Insert Picture Description

It can be seen from the above:

  • After the thread is created it will be in NEW (New) state, starts running after a call to start () method, this time the thread is READY (run) state.
  • Threads running state can be obtained CPU time slice (TimeSlice) is after the RUNNING (running) state.

Hidden operating system Java Virtual Machine (JVM) and the READY RUNNING state, it can only be seen RUNNABLE state (Figure source: HowToDoInJava: Java Thread Life Cycle and Thread States), so Java system is generally referred to as the two states RUNNABLE (running) state.

Here Insert Picture Description

  • When the thread executing wait () method, the thread enters WAITING (waiting) state.
  • The thread into a wait state need to rely on other threads notice to be able to return to operational status, and TIME_WAITING (timeout wait) state the equivalent of adding wait states on the basis of the timeout limit on, for example by sleep (long millis) method or wait (long millis) method can be Java thread into TIMED WAITING state.
  • After the timeout arrives Java thread will return to RUNNABLE state. When a thread calls a synchronization method, in the absence of acquired lock, the thread will enter into BLOCKED (blocked) state. After executing threads run Runnable () method will enter into TERMINATED (terminated) state.

Below we explain in detail, state transition methods required.

Thread start start ()

After the thread is created it will be in NEW (New) state, starts running after a call to start () method, this time the thread is READY (run) state.
But the Thread class also provides a run () method, the direct method calls the run method and start what difference does it, we have to demonstrate it through a classic case.

Thread class distinction run () and start () of
public static void main(String[] args) {
	Thread thread = new Thread(){
	     public void run() {
	         pong();
	     }
	 };
	 thread.run();
	//        thread.start();
	 System.out.println("Ping ");
    }
static void pong() {
	try {
	     Thread.sleep(100);
	 } catch (InterruptedException e) {
	     e.printStackTrace();
	 }
	 System.out.println("Pong ");
}

After executing the program can be found
when you call the run method, print "Pong Ping"
when the start method is called print "Ping Pong"
This explains, did not open the thread when you call the run () method, so the program is executed sequentially, so the print result is "Pong Ping". The calls start () method to open the child thread again dormant "Pong" 100ms after printing, so the print result as "Ping Pong".

  • Directly call run method, it will be treated as an ordinary method invocation, executed in the main thread.
  • Call start () method will start a thread and thread into the ready state, when assigned to the time slot after you can start to run. start () performs the appropriate preparations thread, and then automatically execute run (content method). (Only calls start () method after, Java will be the operating system thread object and the actual object mapping, perform again run () method.)

Thread.yield () thread concessions

After calling thread will be seen from the above Thread.yield () transition from RUNNING state to the READY state
due to the Java virtual machine operating system and the species READY RUNNING two states collectively referred to as RUNNABLE state, so Thread.yield () method in the Java level It is accomplished in view RUNNABLE state.

Although the thread transition from RUNNING state to READY state, but this does not mean that the thread will certainly be interrupted (not performed), but gave up the thread's time slice access, cpu will perform again from the numerous state in the selection, that is, the current is just that thread is still likely to be executed again, not to say you will perform other threads in the thread does not perform the next to.
So yield less accurate translation for the thread concessions, it is possible for the step, people are not willing, then himself Sipilailian continued to implement.

Thread.yield (), the current thread must call this method, the current thread to give up CPU time slice acquired, but does not release the lock resources by running state to the ready state, choose to let OS thread again. Role: let the same priority thread execution by turns, but does not guarantee that will take turns to perform. We can not guarantee the actual yield () to achieve the purpose of concessions, because concessions threads may also be selected again thread scheduler. Thread.yield () does not cause obstruction. This method sleep () is similar, but not specified by the user to pause long.

join()

After ThreadA thread execution method ThreadB.join () method, ThreadA have to wait ThreadB perform complete, ThreadA in order to continue their work

thread.join () / thread.join (long millis), thread the current method call join other thread t, the current thread into the WAITING / TIMED_WAITING state will not release the current thread already holds the object lock. Thread or finished millis time t to the current state of the thread enters RUNNABLE general, it is also possible to enter BLOCKED state (wait because the join is implemented based).

And wait for notification

wait() And sleep()
wait()

obj.wait (), the current thread calls the object's wait () method, the current thread releases the object lock, into the waiting queue. Rely notify () / notifyAll () Wake or wait (long timeout) timeout time to automatically wake.

sleep()

Thread.sleep (long millis), the current thread must call this method, the current thread into the TIMED_WAITING state, but does not release the object lock, automatic wake up after millis thread into the ready state. Role: The best way to give the opportunity to perform other threads.

sleep () and wait () method differences and similarities
  • Both main difference is that: sleep method does not release the lock, and wait method releases the lock.
  • Both can suspend execution thread.
  • Wait typically used for inter-thread interactions / communication, sleep is often used to pause execution.
  • After the wait () method is called, the thread will not automatically wake up, you need to notify the other thread calls the same object () or notifyAll () method. After the sleep () method execution is completed, the thread will automatically wake. Or you can use wait (long timeout) after the timeout thread will automatically wake.
notify()/notifyAll()

obj.notify () wake up a single thread waiting on this object's monitor, the choice is arbitrary. notifyAll () wakes up all threads waiting on this object's monitor.

notify () / notifyAll () Who should use?

You should try to use notifyAll () method, because notify () possible signal loss occurs.

Waiting and notification standards paradigm

Wait for the party:

  1. Acquiring the lock object;
  2. Cycling in determining whether the conditions are met, the method does not meet the call wait
  3. Execute business logic conditions are met

Notify Party

  1. Acquiring an object lock
  2. Changing conditions
  3. Inform all threads waiting on the object
public class Express {
    public final static String CITY = "ShangHai";
    private int km;/*快递运输里程数*/
    private String site;/*快递到达地点*/

    public Express() {
    }

    public Express(int km, String site) {
        this.km = km;
        this.site = site;
    }

    /* 变化公里数,然后通知处于wait状态并需要处理公里数的线程进行业务处理*/
    //通知方
    public synchronized void changeKm(){//synchronized 关键字获取锁
    	this.km = 101;//改变条件
    	notifyAll();//通知所有在等待该对象的线程,这里可改为notify()测试一下俩者的区别。
    	//其他的业务代码
    }

    /* 变化地点,然后通知处于wait状态并需要处理地点的线程进行业务处理*/
    public synchronized void changeSite(){
    	this.site = "BeiJing";
    	notify();
    }

    public synchronized void waitKm(){//synchronized 关键字获取锁
    	while(this.km<=100) {//循环里判断条件是否满足,不满足调用wait方法
    		try {
				wait();
				System.out.println("check km thread["+Thread.currentThread().getId()
						+"] is be notifed.");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	System.out.println("the km is"+this.km+",I will change db.");//条件满足执行业务逻辑

    }

    public synchronized void waitSite(){
    	while(CITY.equals(this.site)) {
    		try {
				wait();
				System.out.println("check site thread["+Thread.currentThread().getId()
						+"] is be notifed.");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	System.out.println("the site is"+this.site+",I will call user.");
    }
}

public class TestExpress {
    private static Express express = new Express(0,Express.CITY);

    /*检查里程数变化的线程,不满足条件,线程一直等待*/
    private static class CheckKm extends Thread{
        @Override
        public void run() {
        	express.waitKm();
        }
    }

    /*检查地点变化的线程,不满足条件,线程一直等待*/
    private static class CheckSite extends Thread{
        @Override
        public void run() {
        	express.waitSite();
        }
    }

 public static void main(String[] args) throws InterruptedException {
     for(int i=0;i<3;i++){//三个线程
         new CheckSite().start();
     }
     for(int i=0;i<3;i++){//里程数的变化
         new CheckKm().start();
     }

     Thread.sleep(1000);
     express.changeKm();//快递地点变化
 }

The code output is as follows:

check km thread[17] is be notifed.
the km is101,I will change db.
check km thread[16] is be notifed.
the km is101,I will change db.
check km thread[15] is be notifed.
the km is101,I will change db.
check site thread[14] is be notifed.
check site thread[13] is be notifed.
check site thread[12] is be notifed.

With notifyAll () method may wake up all the threads waiting on this object's monitor, the code to run properly.
If you use notify () method, we change the main method in the value km notifying party calls notify () wakes up only one thread, but we started six threads, three km of listening, listening site of three so notify wakes up only one thread, it is possible to wake up the thread not wait square km, resulting in a deadlock.

Timeout waiting mode

Due to the above, the classic waiting / notification standards paradigm, do not wait for a timeout, that is, consumers (waiting party) after obtaining the lock, if the condition is not met, the producer would have been waiting in a waiting state until conditions change, in Some practical applications, this would be a huge waste of resources, reduce operating efficiency.
It is possible for consumers above mode (waiting party) to do some small changes:
long overtime = now+T; long remain = T;//等待的持续时间 while(result不满足条件&& remain>0){ wait(remain); remain = overtime – now;//等待剩下的持续时间 } return result;

Call yield (), sleep (), wait (), notify () methods such as the impact on the lock?
  • yield (): After the thread executing yield () method does not release the lock
  • sleep (): After performing sleep () method thread, does not release the lock
  • wait (): calls the wait () method before, the thread must hold the lock when you call, the lock will be released when the wait () method returns, the lock will be released
  • notify (): Before calling the method, it is necessary to hold the lock, call notify () method itself does not release the lock

reference

  • https://snailclimb.top/JavaGuide/#/?id=java
  • https://blog.csdn.net/pange1991/article/details/53860651
  • https://www.jianshu.com/p/98b68c97df9b
  • "Java core technology Volume"
  • "Java programming ideas"
Published 32 original articles · won praise 13 · views 30000 +

Guess you like

Origin blog.csdn.net/weixin_43519048/article/details/104446402