參考文章:
1.創建多線程有四種方式
https://blog.csdn.net/YTREE_BJ/article/details/92761104
https://www.cnblogs.com/zhou-test/p/9811771.html
3.線程的BLOCK、WAITING、TIMED_WAITING狀態
https://blog.csdn.net/weixin_41485592/article/details/103958333
線程的狀態
在進行多線程編程之前,要先知道線程都有哪幾種狀態。
線程的狀態在 java.lang.Thread.State 有定義:
/**
* A thread state. A thread can be in one of the following states:
* <ul>
* <li>{@link #NEW}<br>
* A thread that has not yet started is in this state.
* </li>
* <li>{@link #RUNNABLE}<br>
* A thread executing in the Java virtual machine is in this state.
* </li>
* <li>{@link #BLOCKED}<br>
* A thread that is blocked waiting for a monitor lock
* is in this state.
* </li>
* <li>{@link #WAITING}<br>
* A thread that is waiting indefinitely for another thread to
* perform a particular action is in this state.
* </li>
* <li>{@link #TIMED_WAITING}<br>
* A thread that is waiting for another thread to perform an action
* for up to a specified waiting time is in this state.
* </li>
* <li>{@link #TERMINATED}<br>
* A thread that has exited is in this state.
* </li>
* </ul>
*
* <p>
* A thread can be in only one state at a given point in time.
* These states are virtual machine states which do not reflect
* any operating system thread states.
*
* @since 1.5
* @see #getState
*/
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
<li>{@link #NEW}<br> * A thread that has not yet started is in this state. * </li> 創建後尚未啓動的線程處於這種狀態 * <li>{@link #RUNNABLE}<br> * A thread executing in the Java virtual machine is in this state. * </li> Runable包括了操作系統線程狀態的Running和Ready,也就是處於此狀態的線程有可能正在執行,也有可能正在等待着CPU爲它分配執行時間。 * <li>{@link #BLOCKED}<br> * A thread that is blocked waiting for a monitor lock * is in this state. * </li> 線程被阻塞了,“阻塞狀態”與”等待狀態“的區別是:”阻塞狀態“在等待着獲取到一個排他鎖,這個時間將在另外一個線程放棄這個鎖的時候發生;而”等待狀態“則是在等待一段時間或者喚醒動作的發生。在程序等待進入同步區域的時候,線程將進入這種狀態。 * <li>{@link #WAITING}<br> * A thread that is waiting indefinitely for another thread to * perform a particular action is in this state. * </li> 處於這種狀態的線程不會被分配CPU執行時間。 等待狀態又分爲無限期等待和有限期等待,WAITING 爲無限期等待 處於無限期等待的線程需要被其他線程顯示地喚醒,沒有設置Timeout參數的Object.wait()、沒有設置Timeout參數的Thread.join()方法都會使線程進入無限期等待狀態;
線程處於WAITING狀態的場景。
- 調用Object對象的wait方法,但沒有指定超時值。
- 調用Thread對象的join方法,但沒有指定超時值。
- 調用LockSupport對象的park方法。
* <li>{@link #TIMED_WAITING}<br> * A thread that is waiting for another thread to perform an action * for up to a specified waiting time is in this state. * </li> 當處於一個給定的等待時間時候,線程處於這種狀態 TIMED_WAITING 有限期等待狀態無須等待被其他線程顯示地喚醒,在一定時間之後它們會由系統自動喚醒,Thread.sleep()、設置了Timeout參數的Object.wait()、設置了Timeout參數的Thread.join()方法都會使線程進入有限期等待狀態。 線程處於TIMED_WAITING狀態的場景。 調用Thread.sleep方法。 調用Object對象的wait方法,指定超時值。 調用Thread對象的join方法,指定超時值。 調用LockSupport對象的parkNanos方法。 調用LockSupport對象的parkUntil方法。 * <li>{@link #TERMINATED}<br> * A thread that has exited is in this state. * </li>
已終止線程的線程狀態,線程已經結束執行。
線程狀態間的切換
既然有那麼多的線程狀態,它們之間的狀態轉換如下圖所示
線程間同步的方法
線程有4中同步方法,分別爲wait()、sleep()、notify()和notifyAll()。
wait():使線程處於一種等待狀態,釋放所持有的對象鎖。
sleep():使一個正在運行的線程處於睡眠狀態,是一個靜態方法,調用它時要捕獲InterruptedException異常,不釋放對象鎖。
notify():喚醒一個正在等待狀態的線程。注意調用此方法時,並不能確切知道喚醒的是哪一個等待狀態的線程,是由JVM來決定喚醒哪個線程,不是由線程優先級決定的。
notifyAll():喚醒所有等待狀態的線程,注意並不是給所有喚醒線程一個對象鎖,而是讓它們競爭。
Java 創建線程的4種方式 :
- 繼承Thread類創建多線程
- 實現Runnable接口創建多線程
- 實現Callable接口通過FutureTask包裝器來創建Thread多線程
- 使用ExecutorService、Callable、Future實現有返回結果的線程。
繼承Thread類創建多線程
代碼如下:繼承Thread類
package com.dazhi.thread.multithread;
/**
* 多線程創建,繼承
* @author dazhi
*/
public class MyThread extends Thread{
@Override
public void run() {
for (int i=0; i<10; i++) {
System.out.println(Thread.currentThread().getName() +":"+ i);
}
}
public static void main(String[] args) throws InterruptedException {
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
MyThread thread3 = new MyThread();
thread1.start();
thread2.start();
thread3.start();
}
}
實現Runnable接口創建多線程
實現Runnable接口
package com.dazhi.thread.multithread;
/**
* 多線程創建, 實現Runnable
* @author dazhi
*/
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i=0; i<10; i++) {
System.out.println(Thread.currentThread().getName() +":"+ i);
}
}
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread1 = new Thread(myRunnable, "thread1");
Thread thread2 = new Thread(myRunnable, "thread2");
Thread thread3 = new Thread(myRunnable, "thread3");
thread1.start();
thread2.start();
thread3.start();
}
}
實現Callable接口通過FutureTask包裝器來創建Thread多線程
實現Callable
package thread.multi;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
/**
* Created by szh on 2020/6/15.
*
* @author szh
*/
public class CallableThread implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(10 * 1000);
return "Just do it";
}
public static void main(String[] args) throws Exception {
CallableThread callableThread = new CallableThread();
FutureTask<String> stringFuture = new FutureTask<String>(callableThread);
Thread a = new Thread(stringFuture);
a.start();
System.out.println(stringFuture.get());
}
}
// 運行結果
Just do it
注意 get 會阻塞線程的運行,直到得到返回結果!!
使用ExecutorService、Callable、Future實現有返回結果的線程。
package com.dazhi.thread.multithread;
import java.util.concurrent.*;
/**
* 多線程創建, ExecutorService + Callable + Future
* @author dazhi
*/
public class MyExecutors {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 不提倡的方式創建線程池方式。爲了方便就這樣寫了
ExecutorService executorService = Executors.newFixedThreadPool(5);
Future<Integer> submit = executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return 1234;
}
});
executorService.shutdown();
System.out.println(submit.get());
}
}
// 運行結果
1234Process finished with exit code 0
// 不提倡創建線程池的原因