多執行緒
多執行緒概述
- 多執行緒就是計算機用時運行多個任務
- 但實質上,同一個時間點,只會運行一個任務,只是計算機在不同任務之間來回切換而已,
并發和并行
并行:在同一時間,多個任務分別在多個CPU上進行,
并發:在同一時間,多個任務在同一個CPU交替進行,
執行緒和行程
行程
- 獨立性:行程是一個獨立運行的應用程式,
- 動態性:行程就是一個程式運行的程序,程式開始運行,行程創建,運行接收,行程消亡,
- 并發性:任何行程可以和其他行程并發執行,
執行緒不能單獨存在,執行緒是行程的一部分,一個行程可以有多可執行緒,但必須至少有一個執行緒,
多執行緒實作
- 實作多執行緒方式一:繼承Thread類,Thread類就是執行緒類,要實作多執行緒必須創建Thread類物件,
自定義類通過繼承Thread類,再重寫run() 方法
public class ThreadDemo extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+"的第"+i+"次");
}
}
}
在測驗類中創建自定義類物件
public class TestDemo {
public static void main(String[] args) {
ThreadDemo t1 = new ThreadDemo();
//為執行緒設定名字
t1.setName("執行緒1");
//start() 方法告訴JVM程式會啟用多執行緒,并自動呼叫run() 方法
//直接執行run() 方法,那么就是執行一個普通的單執行緒方法
t1.start();
ThreadDemo t2 = new ThreadDemo();
t2.setName("執行緒2");
t2.start();
}
}
- 實作多執行緒方式二:實作Runnable介面
public class RunnableDemo implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
//讓執行緒停止指定毫秒數
//父類Thread沒有拋出例外,所以子類只能自己捕獲例外
try {
Thread.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//呼叫Thread的靜態方法currentThread(),可以直接獲取當前的行程
System.out.println("這是執行緒"+Thread.currentThread().getName()+i);
}
}
}
測驗類
public class TestDemo2 {
public static void main(String[] args) {
RunnableDemo ra = new RunnableDemo();
//呼叫Thread() 的帶參方法,傳入一個Runnable的實作類物件
Thread thread = new Thread(ra);
thread.setName("西安");
//為該執行緒設定優先級1(min)-10(max),優先級越高,搶占CPU的幾率就越大,但不會達到100%
thread.setPriority(10);
//獲取優先級
System.out.println(thread.getPriority());
thread.start();
Thread thread2 = new Thread(ra);
thread2.setPriority(1);
//獲取優先級
System.out.println(thread2.getPriority());
thread2.setName("杭州");
thread2.start();
}
}
- 實作Callable介面
public class CallableDemo implements Callable<String> {
@Override
public String call() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println("和班主任請假第"+i+"次");
}
return "同意";
}
}
測驗類
public class TestDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CallableDemo cd = new CallableDemo();
FutureTask<String> ft = new FutureTask<>(cd);
Thread thread = new Thread(ft);
thread.start();
FutureTask<String> ft2 = new FutureTask<>(cd);
Thread thread2 = new Thread(ft2);
thread2.start();
//注意如果在start方法之前 呼叫get() 方法,意味著在開啟執行緒之前獲取回傳值,但是此時執行緒尚未開啟,這就照成死鎖
String o = ft.get();
String o2 = ft2.get();
System.out.println(o);
System.out.println(o2);
}
}
總結如下:
- 方式一:通過自定義類繼承Thread的方式,
優點:子類可以直接呼叫父類的方法,缺點,對子類限制比較大,不能再繼承其他類
- 方式二 :通過自定義類實作Runnable介面的方式,
優點:通過實作介面的方式,子類還可以繼承其他類,拓展性更強
缺點:不能直接啟用多執行緒,需要先創建Runnable實作類物件,再使用Thread的帶參構造傳入Runnable實作類物件,再通過Thread物件啟用多執行緒
- 方式三:通過自定義類實作Callable介面的方式
優點:通過實作介面的方式,子類還可以繼承其他類,執行執行緒后還可以回傳值
缺點:不能直接啟用多執行緒,需要先需要先創建Callable實作類物件,再使用FutureTask的帶參構造傳入Runnable實作類物件,再使用Thread的帶參構造傳入FutureTask類物件,再通過Thread物件啟用多執行緒
守護執行緒
守護執行緒會因為普通執行緒結束而結束,無論守護執行緒是否執行完畢
代碼如下:
public class DaemonDemo {
public static void main(String[] args) {
Test1 t1 = new Test1();
t1.setName("主人");
t1.setPriority(1);
t1.start();
Test2 t2 = new Test2();
t2.setDaemon(true);
t2.setName("保鏢");
t2.setPriority(10);
t2.start();
}
}
/**
* 主人執行緒
*/
public class Test1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+"..."+i);
}
}
}
/**
* 保鏢執行緒
*/
public class Test2 extends Thread{
@Override
public void run() {
try {
Thread.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
for (int i = 0; i < 100; i++) {
System.out.println(getName()+"==="+i);
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/547894.html
標籤:其他
上一篇:day11-SpringBoot中注入Servlet&Filter&Listener
下一篇:理解MVCC
