java 多執行緒介紹
多執行緒
- 什麼是執行緒
- 執行緒是程式執行的一條路徑, 一個程序中可以包含多條執行緒
- 多執行緒併發執行可以提高程式的效率, 可以同時完成多項工作(cpu不斷切換任務)當然多核cpu是不一樣的
多執行緒並行和併發的區別
- 並行就是兩個任務同時執行,就是甲任務進行的同時,乙任務也在進行。(需要多核CPU)
- 併發是指兩個任務都請求執行,而處理器只能按受一個任務,就把這兩個任務安排輪流進行,由於時間間隔較短,使人感覺兩個任務都在執行。
比如:
JVM的啟動是多執行緒的嗎
JVM啟動至少啟動了垃圾回收執行緒和主執行緒,所以是多執行緒的。
多執行緒程式實現的兩種方式
- 繼承Thread
- 定義類繼承Thread
- 重寫run方法
- 把新執行緒要做的事寫在run方法中
- 建立執行緒物件
- 開啟新執行緒, 內部會自動執行run方法
public class Demo2_Thread {
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
for(int i = 0; i < 1000; i++) {
System.out.println("b");
}
}
}
class MyThread extends Thread {
public void run() {
for(int i = 0; i < 1000; i++) {
System.out.println("a");
}
}
}
- 實現Runnable(方法二)
- 定義類實現Runnable介面
- 實現run方法
- 把新執行緒要做的事寫在run方法中
- 建立自定義的Runnable的子類物件
- 建立Thread物件, 傳入Runnable
- 呼叫start()開啟新執行緒, 內部會自動呼叫Runnable的run()方法
public class Demo3_Runnable {
public static void main(String[] args) {
MyRunnable mr = new MyRunnable();
Thread t = new Thread(mr);
t.start();
for(int i = 0; i < 1000; i++) {
System.out.println("b");
}
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
for(int i = 0; i < 1000; i++) {
System.out.println("a");
}
}
}
Runnable 底層也是依賴 Thread的
兩種方式的區別
-
繼承Thread : 由於子類重寫了Thread類的run(), 當呼叫start()時, 直接找子類的run()方法
-
實現Runnable : 建構函式中傳入了Runnable的引用, 成員變數記住了它, start()呼叫run()方法時內部判斷成員變數Runnable的引用是否為空, 不為空編譯時看的是Runnable的run(),執行時執行的是子類的run()方法
-
繼承Thread
- 好處是:可以直接使用Thread類中的方法,程式碼簡單
- 弊端是:如果已經有了父類,就不能用這種方法
-
實現Runnable介面
- 好處是:即使自己定義的執行緒類有了父類也沒關係,因為有了父類也可以實現介面,而且介面是可以多實現的
- 弊端是:不能直接使用Thread中的方法需要先獲取到執行緒物件後,才能得到Thread的方法,程式碼複雜
匿名內部類實現執行緒的兩種方式
繼承Thread類
new Thread() {
public void run() {
for(int i = 0; i < 1000; i++) {
System.out.println("a");
}
}
}.start();
實現Runnable介面
new Thread(new Runnable(){
public void run() {
for(int i = 0; i < 1000; i++) {
System.out.println("b");
}
}
}).start();
獲取名字和設定名字
- 獲取名字
- 通過getName()方法獲取執行緒物件的名字
- 設定名字
- 通過建構函式可以傳入String型別的名字
new Thread("xxx") {
public void run() {
for(int i = 0; i < 1000; i++) {
System.out.println(this.getName() + "***");
}
}
}.start();
new Thread("yyy") {
public void run() {
for(int i = 0; i < 1000; i++) {
System.out.println(this.getName() + "++++");
}
}
}.start();
通過setName(String)方法可以設定執行緒物件的名字
Thread t1 = new Thread() {
public void run() {
for(int i = 0; i < 1000; i++) {
System.out.println(this.getName() + "*****");
}
}
};
Thread t2 = new Thread() {
public void run() {
for(int i = 0; i < 1000; i++) {
System.out.println(this.getName() + "+++++");
}
}
};
t1.setName("xixi");
t2.setName("哈哈");
t1.start();
t2.start();
獲取當前執行緒的物件
Thread.currentThread(), 主執行緒也可以獲取
new Thread(new Runnable() {
public void run() {
for(int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName() + "*****");
}
}
}).start();
new Thread(new Runnable() {
public void run() {
for(int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName() + "++++");
}
}
}).start();
Thread.currentThread().setName("我是主執行緒");
System.out.println(Thread.currentThread().getName());
休眠執行緒
- Thread.sleep(毫秒,納秒), 控制當前執行緒休眠若干毫秒1秒= 1000毫秒 1秒 = 1000 * 1000 * 1000納秒 1000000000
守護執行緒
- setDaemon(), 設定一個執行緒為守護執行緒, 該執行緒不會單獨執行, 當其他非守護執行緒都執行結束後, 自動退出
Thread t1 = new Thread() {
public void run() {
for(int i = 0; i < 50; i++) {
System.out.println(getName() + "****");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t2 = new Thread() {
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println(getName() + "++++");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t1.setDaemon(true); //將t1設定為守護執行緒
t1.start();
t2.start();
加入執行緒
- join(), 當前執行緒暫停, 等待指定的執行緒執行結束後, 當前執行緒再繼續
- join(int), 可以等待指定的毫秒之後繼續
final Thread t1 = new Thread() {
public void run() {
for(int i = 0; i < 50; i++) {
System.out.println(getName() + "*****");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t2 = new Thread() {
public void run() {
for(int i = 0; i < 50; i++) {
if(i == 2) {
try {
t1.join(30);
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getName() + "+++++");
}
}
};
t1.start();
t2.start();
禮讓執行緒和設定執行緒的優先順序
- yield()讓出cpu
- setPriority()設定執行緒的優先順序
同步程式碼塊
- 什麼情況下需要同步
- 當多執行緒併發, 有多段程式碼同時執行時, 我們希望某一段程式碼執行的過程中CPU不要切換到其他執行緒工作. 這時就需要同步.
- 如果兩段程式碼是同步的, 那麼同一時間只能執行一段, 在一段程式碼沒執行結束之前, 不會執行另外一段程式碼.
- 同步程式碼塊
- 使用synchronized關鍵字加上一個鎖物件來定義一段程式碼, 這就叫同步程式碼塊
- 多個同步程式碼塊如果使用相同的鎖物件, 那麼他們就是同步的
public static void main(String[] args) {
final Printer p = new Printer();
new Thread() {
public void run() {
while(true) {
p.print1();
}
}
}.start();
new Thread() {
public void run() {
while(true) {
p.print2();
}
}
}.start();
}
}
class Printer {
Demo d = new Demo();
public static void print1() {
synchronized(d){
//鎖物件可以是任意物件,但是被鎖的程式碼需要保證是同一把鎖,不能用匿名物件
System.out.print("A");
System.out.print("B");
System.out.print("C");
System.out.print("D");
System.out.print("\r\n");
}
}
public static void print2() {
synchronized(d){
System.out.print("1");
System.out.print("2");
System.out.print("3");
System.out.print("4");
System.out.print("\r\n");
}
}
}
同步方法
- 使用synchronized關鍵字修飾一個方法, 該方法中所有的程式碼都是同步的
class Printer {
public static void print1() {
synchronized(Printer.class){
//鎖物件可以是任意物件,但是被鎖的程式碼需要保證是同一把鎖,不能用匿名物件
System.out.print("A");
System.out.print("B");
System.out.print("C");
System.out.print("D");
System.out.print("\r\n");
}
}
/*
* 非靜態同步函式的鎖是:this
* 靜態的同步函式的鎖是:位元組碼物件
*/
public static synchronized void print2() {
System.out.print("1");
System.out.print("2");
System.out.print("3");
System.out.print("4");
System.out.print("\r\n");
}
}
單例設計模式
- 單例設計模式:保證類在記憶體中只有一個物件。
- 如何保證類在記憶體中只有一個物件呢?
- (1)控制類的建立,不讓其他類來建立本類的物件。private
- (2)在本類中定義一個本類的物件。Singleton s;
- (3)提供公共的訪問方式。 public static Singleton getInstance(){return s}
- 單例寫法兩種:
- (1)餓漢式 開發用這種方式。
class Singleton {
//1,私有建構函式
private Singleton(){}
//2,建立本類物件
private static Singleton s = new Singleton();
//3,對外提供公共的訪問方法
public static Singleton getInstance() {
return s;
}
public static void print() {
System.out.println("11111111111");
}
}
- (2)懶漢式 面試寫這種方式。多執行緒的問題?
//懶漢式,單例的延遲載入模式
class Singleton {
//1,私有建構函式
private Singleton(){}
//2,宣告一個本類的引用
private static Singleton s;
//3,對外提供公共的訪問方法
public static Singleton getInstance() {
if(s == null)
//執行緒1,執行緒2 執行緒不安全
s = new Singleton();
return s;
}
}
餓漢和懶漢的區別:
1.餓漢空間換時間,懶漢相反
2.懶漢執行緒不安全
- (3)第三種格式
class Singleton {
private Singleton() {}
public static final Singleton s = new Singleton();
//final是最終的意思,被final修飾的變數不可以被更改
}
Runtime類是一個單例類
Timer
它是java的定時器,可以定時執行一個任務,或者間隔一段時間重複執行一個任務
schedule()方法
public class DTimer {
public static void main(String[] args) throws InterruptedException {
Timer t = new Timer();
t.schedule(new MyTimerTask(), new Date(118,12,7,10,54,20),5000);
//第一個引數 是一個繼承TimerTask類的類 物件 繼承要重寫run()方法 ,也就是要多執行緒執行內容
//第二個引數是Date物件
//第三個引數是間隔時間
}
}
class MyTimerTask extends TimerTask {
public void run() {
System.out.println("該敲程式碼了");
}
}
等待執行緒和喚醒執行緒
物件.wait()讓一個執行緒等待
物件.notify()任意喚醒一個執行緒
物件.notify()喚醒所有等待執行緒
注意點:
- 1,在同步程式碼塊中,用哪個物件鎖,就用哪個物件呼叫wait方法
- 2,為什麼wait方法和notify方法定義在Object這類中?
因為鎖物件可以是任意物件,Object是所有的類的基類,所以wait方法和notify方法需要定義在Object這個類中 - 3,sleep方法和wait方法的區別?
a,sleep方法必須傳入引數,引數就是時間,時間到了自動醒來
wait方法可以傳入引數也可以不傳入引數,傳入引數就是在引數的時間結束後等待,不傳入引數就是直接等待
b,sleep方法在同步函式或同步程式碼塊中,不釋放鎖,睡著了也抱著鎖睡
wait方法在同步函式或者同步程式碼塊中,釋放鎖
多個執行緒的執行問題(互斥鎖運用)
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Demo3_ReentrantLock {
public static void main(String[] args) {
final Printer3 p = new Printer3();
new Thread() {
public
相關推薦
java 多執行緒介紹
多執行緒
什麼是執行緒
執行緒是程式執行的一條路徑, 一個程序中可以包含多條執行緒
多執行緒併發執行可以提高程式的效率, 可以同時完成多項工作(cpu不斷切換任務)當然多核cpu是不一樣的
多執行緒並行和併發的區別
java定時器類Timer和多執行緒介紹及例項
任務要求:
完成一個java application應用程式,使用定時器程式設計,在實時顯示當前時間,每1秒時鐘內容更新一次。
完成一個java application應用程式,在應用程式主程序中新開一個執行緒,此執行緒進行死迴圈,每1秒被啟用一次,啟用時即在
《Java併發性和多執行緒介紹》-Java TheadLocal
原文連結 作者:Jakob Jenkov 檢視全部文章
Java中的ThreadLocal類可以讓你建立的變數只被同一個執行緒進行讀和寫操作。因此,儘管有兩個執行緒同時執行一段相同的程式碼,而且這段程式碼又有一個指向同一個ThreadLocal變數的引用,但是這兩個執行緒依然不能看到彼此的
Java併發性和多執行緒介紹目錄
ThreadPoolExecutor.addIfUnderCorePoolSize(Runnable firstTask)
{
Thread t = null;
final ReentrantLock mainLock = this.mainLock;
ma
Java併發性和多執行緒介紹
作者:Jakob Jenkov 譯者:Simon-SZ 校對:方騰飛
在過去單CPU時代,單任務在一個時間點只能執行單一程式。之後發展到多工階段,計算機能在同一時間點並行執行多工或多程序。雖然並不是真正意義上的“同一時間點”,而是多個任務或程序共享一個CPU,並交由作業系統來完成多工間對C
Java多執行緒程式設計-(3)-執行緒本地ThreadLocal的介紹與使用
原文出自 : https://blog.csdn.net/xlgen157387/article/details/78114278
ThreadLocal簡介
我們通過上兩篇的學習,我們已經知道了變數值的共享可以使用public static變數的形式,所有的執行緒都使
Java多執行緒(五)、多執行緒其他知識簡要介紹
一、執行緒組
[java]
view plain
copy
/**
* A thread gr
三、JAVA多執行緒:Thread API詳細介紹 (sleep、Interrupt、Join、TimeUnit、yield、interrupted、執行緒優先順序 )
本章深入分析了Thread的所有API,熟練掌握Thread的API是學好Thread的前提。
執行緒sleep
sleep是一個靜態方法,一共有兩個過載方法,一個需要傳入毫秒數,另一個既要傳入毫秒數又要傳入納秒數。
sleep方法介紹
Java多執行緒--執行緒池介紹
為什麼會出現執行緒池?思考執行緒池問題時,我總是會和資料庫連線池聯想到一起,我個人覺得它們兩者的核心思想有很大的相像之處,它們都是利用了一種"池化"的思想,目的都是為了減少連線的建立和銷燬. 在多執行
java多執行緒—執行緒的基本介紹
程序和執行緒:
程序是程式的一次動態執行過程,經歷了從程式碼的載入、執行到執行完畢的一個完整的過程,這個過程也是程序本身從產生、發展到最終消亡的過程。
多執行緒是實現併發機制的一種有效手段。程序和執行緒一樣,都是實現併發的一個基本單位。
java實現多執行
java多執行緒之守護執行緒Daemon()和Join()介紹
最近看了些多執行緒相關的同樣的避免忘了:我們先模擬一個需求,在http請求的時候我們都會發心跳包,就會一遍又一遍的去檢查心跳是否存在,但是當這個請求不用的時候我們採取什麼方式來把它關閉掉呢?因為Stop的方法我們已經被java淘汰掉了.這時候我們可以拿守護執行緒來做著件事:p
Java併發性和多執行緒介紹、優缺點
在過去單核CPU時代,單任務在一個時間點只能執行單一程式。之後發展到多工階段,計算機能在同一時間點並行執行多工或多程序。雖然並不是真正意義上的“同一時間點”,而是多個任務或程序共享一個CPU,並交由
java多執行緒總結-同步容器與併發容器的對比與介紹
目錄
1 容器集簡單介紹
2 同步容器
3 併發容器
4 案例講解
4.1 Map/Set
4.2 List
4.3 Queue
4.3.1 C
Java多執行緒實現電影院售票案例
某電影院目前正在上映賀歲大片,共有100張票,而它有3個售票視窗,請設計一個程式模擬該電影院售票。
定義Sell類實現Runnable介面,很好的解決了單繼承共享資源問題
public class Sell implements Runnable {
// 定義100張票,三個售票
java多執行緒物件鎖、類鎖、同步機制詳解
1.在java多執行緒程式設計中物件鎖、類鎖、同步機制synchronized詳解:
物件鎖:在java中每個物件都有一個唯一的鎖,物件鎖用於物件例項方法或者一個物件例項上面的。
類鎖:是用於一個類靜態方法或者class物件的,一個
Java 多執行緒實現死鎖場景
簡述:
《Java 程式設計思想》 P718 ~ P722
模擬死鎖的場景, 三個人 三根筷子,每個人需要拿到身邊的兩根筷子才能開始吃飯
出現死鎖的場景是,三個人都拿到了右邊的筷子,但是由於筷子都被搶佔,均無法獲得左邊的筷子
Chopstick.java
Java 多執行緒 join和interrupt 方法
簡述:
使用Java多執行緒中join和interrupt函式
《Java程式設計思想》 P669 ~ P670
一個執行緒可以再其他執行緒上呼叫join()方法,其效果是等待一段時間直到第二個執行緒結束才繼續執行。
如果某個執行緒在另一個執行緒t上呼叫t.join(), 此
Java 多執行緒 CountDownLatch 試用
簡述:
使用Java多執行緒的庫,包括
ExecutorService執行緒池,
CountDownLatch執行緒執行控制(知道所有啟動的執行緒呼叫完成後,函式才會繼續執行)
package test.anialy.multithread;
import java.ut
Java多執行緒中Synchronized簡介和Static Synchronized的區別
在進行Java開發時,多執行緒的開發是經常會使用的。首先會問一個小問題啊,在Java中有幾種方法可以建立一個執行緒?
我給的答案是3種。(如果還有其他的請留言告訴我哈。)
1、建立直接繼承自Thread類建立執行緒子類。
步驟如下:a 定義一個子類,同時
Java多執行緒學習與總結(Join)
join()方法的用法:
join()是主執行緒 等待子執行緒的終止。也就是在子執行緒呼叫了 join() 方法後面的程式碼,只有等到子執行緒結束了才能執行。
例子如下:
Java程式碼
p