執行緒、執行緒匿名內部類、解決執行緒不安全的方式
阿新 • • 發佈:2018-12-26
執行緒
執行緒:正在執行的程式,是程式的執行路徑;多線性
程序:是應用程式的載體,程式執行在虛擬機器中。一個應用軟體對應一個程序。
一個程序包含多個執行緒,一個執行緒對應一個程序。
好處:提高軟體的執行效率
多執行緒的執行原理
在同一時刻只能有一個執行緒正在使用CPU,作業系統設計了CPU的排程方式。
- 分時呼叫:平均分配使用CPU的使用時間
- 搶佔式排程:根據執行緒的優先順序分配CPU資源
開發多執行緒的方式
- 繼承Thread類
- 實現Runnable介面
Thread類
構造方法:
成員方法:
- int getPriority() 返回執行緒的優先順序。
- String getName() 返回該執行緒的名稱。
- void run()執行執行緒邏輯的程式碼
- void start()開啟執行緒,使執行緒處於就緒狀態,等待CPU的排程。
執行緒使用
定義子執行緒類(繼承Thread或者實現Runable介面),重寫run()方法。
建立執行緒物件,呼叫start()方法。
子執行緒
public class DemoThread extends Thread { public DemoThread(){} public DemoThread(String name){ super(name); } @Override public void run() { Thread demo = Thread.currentThread(); String demoName = demo.getName(); System.out.println(demoName); } }
主執行緒
public class DemoMain { public static void main(String[] args) { Thread main = Thread.currentThread(); String mainName = main.getName(); System.out.println(mainName); //建立子執行緒的物件 DemoThread dt=new DemoThread("我是子執行緒"); dt.start(); System.out.println("主執行緒"); } }
實現Runnable介面
- 定義類實現Runnable介面,重寫run()方法(執行緒執行的程式碼)
- 建立子執行緒任務物件
- 建立子執行緒物件
- 呼叫start()方法。
子執行緒
public class DemoRunable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
主執行緒
public class MainRunnable {
public static void main(String[] args) {
//建立子任務
DemoRunable dr=new DemoRunable();
//建立子執行緒物件
Thread td=new Thread(dr,"子執行緒");
td.start();
}
}
兩種方式的區別
- 繼承Thread類, 任務與子執行緒程式碼 耦合(關聯性)到一起。
- 實現Runnable介面,把任務程式碼和子執行緒的程式碼分開(解耦性強)
- 繼承擴充套件性差、不能繼承其他的父類,只能繼承一個父類。
執行緒匿名內部類使用
/**
*只調用一次執行緒
* @author YandeHu
*
*/
public class DemoInner {
public static void main(String[] args) {
new Thread(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
System.out.println("Thread繼承子執行緒匿名內部類的程式碼");
}
}.start();
Runnable r=new Runnable(){
@Override
public void run() {
System.out.println("Runnable1 匿名自內部物件");
}
};
Thread td=new Thread(r);
td.start();
new Thread(new Runnable(){
@Override
public void run() {
System.out.println("Runnable2 匿名自內部物件");
}
}).start();
}
}
解決執行緒不安全的方式
保證修改共享資料的程式碼在同一時刻只能一個執行緒訪問,保證執行緒是同步的。
使用同步程式碼塊
- 使用關鍵字 syncronized 修改共享程式碼塊
- 同步:程式碼一行一行的往下執行
- 非同步:多個執行緒同時執行
- 鎖物件:任意的物件型別 ,只有執行緒拿到此物件,才能執行程式碼。
public class TiketRunnable implements Runnable {
int tiketNumber=100; //鎖物件 只有獲得鎖物件的執行緒才可以執行 Object obj=new Object(); @Override public void run() { while(true){ synchronized (obj) { if(tiketNumber>0){ try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("執行緒"+Thread.currentThread().getName()+" 正在賣"+(tiketNumber--)+"張票"); } } } } }
Lock介面
Lock lock=new ReentrantLock();
//重寫run方法
public void run() {
lock.lock();
同步程式碼
lock.unlock();
}
Lock lock=new ReentrantLock();
@Override
public void run() {
while(true){
lock.lock();
if(tiketNumber>0){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("執行緒"+Thread.currentThread().getName()+" 正在賣"+(tiketNumber--)+"張票");
}
lock.unlock();
}