java多執行緒-初探(一)
阿新 • • 發佈:2018-12-05
啥是多執行緒?跟程序又是啥關係?
比方說:我去洗手,洗完手去吃飯。
程序(Processor)
洗手跟吃飯是兩個程序。
執行緒(Thread)
在洗手的程序裡,我同時聽歌,還唱歌。那這裡洗手是一個程序,聽歌跟唱歌是兩個執行緒。
在吃飯的程序裡,我同時聽歌,還唱歌。那這裡吃飯是一個程序,聽歌跟唱歌是兩個執行緒。
吃飯跟洗手兩個程序之間的執行緒互不干擾,同個程序之間的執行緒存在鎖、等待、喚醒等等等機制。
多執行緒:同一個程序內做多件事,每件事是一個執行緒
這裡建立一個普通java專案。
單執行緒示例
以吃飯為例,只有聽完歌才能唱歌,無法邊聽邊唱。
class Main
public class Main { /** * 吃飯 * @param args */ public static void main(String[] args) { Song song = new Song(); while (!song.listenIsZero()) song.doThing("listen") ; while (!song.singIsZero()) song.doThing("sing") ; System.out.println("執行完成!"); } }
class Song
public class Song { // 待唱的歌曲數量 private int singNum = 5 ; // 待聽的歌曲數量 private int listenNum = 5 ; public boolean singIsZero(){ return singNum == 0 ; } public boolean listenIsZero(){ return listenNum == 0 ; } public void doThing(String thing){ switch (thing){ case "sing" : doSing(); break; case "listen" : doListen(); break; } } public void doSing(){ try { // 唱歌需要時間,加時間能體現多執行緒的效果 Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("唱了一首歌,剩餘:" + singNum-- +"首未唱"); if (singIsZero()) System.out.println("唱完了!"); } public void doListen(){ try { // 聽歌需要時間,加時間能體現多執行緒的效果 Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("聽了一首歌,剩餘:" + listenNum-- +"首未聽"); if (listenIsZero()) System.out.println("聽完了!"); } }
執行結果
多執行緒示例(繼承Thread類)
可以在吃飯的程序裡,邊聽歌邊唱歌。同時進行。
建立一個類負責聽歌或者唱歌,繼承Thread,重寫run函式。
建立兩個執行緒,都start之後可以觀察到兩個執行緒同時呼叫doThing函式。
class Main
public class Main {
/**
* 吃飯
* @param args
*/
public static void main(String[] args) {
// 單執行緒示例
/*Song song = new Song();
while (!song.listenIsZero())
song.doThing("listen") ;
while (!song.singIsZero())
song.doThing("sing") ;*/
// 多執行緒示例
SongThread listen = new SongThread("listen", new Song());
SongThread sing = new SongThread("sing", new Song());
// 啟動兩個執行緒
listen.start();
sing.start();
System.out.println("執行完成!");
}
}
class SongThread
public class SongThread extends Thread{
private Song song ;
private String thing ;
public SongThread(String thing, Song song){
this.song = song;
this.thing = thing;
}
public void run(){
switch (thing){
case "listen" : while (!song.listenIsZero()) song.doListen(); break;
case "sing" : while (!song.singIsZero()) song.doSing(); break;
}
}
}
執行結果
多執行緒示例(實現Runnable介面)
建立一個類實現Runnable介面,然後new Thread的時候將實現類傳參之後start。
Thread與Runnable的關係:Thread類實現了Runnable介面。
class Main
public class Main {
/**
* 吃飯
* @param args
*/
public static void main(String[] args) {
// 單執行緒示例
/*Song song = new Song();
while (!song.listenIsZero())
song.doThing("listen") ;
while (!song.singIsZero())
song.doThing("sing") ;*/
/*// 多執行緒示例 Thread
SongThread listen = new SongThread("listen", new Song());
SongThread sing = new SongThread("sing", new Song());
// 啟動兩個執行緒
listen.start();
sing.start();
System.out.println("執行完成!");*/
// 多執行緒示例 實現Runnable介面
SongRunnable listen = new SongRunnable("listen", new Song());
SongRunnable sing = new SongRunnable("sing", new Song());
// 啟動兩個執行緒
new Thread(listen).start();
new Thread(sing).start();
}
}
class SongRunnable
public class SongRunnable implements Runnable{
private Song song ;
private String thing ;
public SongRunnable(String thing, Song song){
this.song = song;
this.thing = thing;
}
public void run(){
switch (thing){
case "listen" : while (!song.listenIsZero()) song.doListen(); break;
case "sing" : while (!song.singIsZero()) song.doSing(); break;
}
}
}
執行結果
java多執行緒-初探(二)
實際業務應用場景舉例
1.後臺需要定時給資料庫100w個使用者傳送提醒郵件。
啟動兩個執行緒分別給50w個使用者發郵件。
2.不影響使用者情況下記錄使用者操作日誌(非同步)
啟動一個執行緒去單獨執行記錄日誌的操作。