微信公眾號 wx.chooseImage拍照或從手機相簿中選圖介面
阿新 • • 發佈:2020-09-02
繼承Thread類使用run()方法使用執行緒功能
MyThread myThread = new MyThread();
MyThread myThread1 = new MyThread();
new 兩個物件
myThread.start();
myThread1.start();
呼叫兩個執行緒,底層執行的還是run();
如果直接執行run()方法,就是使用兩個物件的方法,和執行緒沒關係
設定執行緒名字:
一。
myThread.setName("dog");
myThread1.setName("cat");
呼叫Thread的方法設定執行緒名字
二。
public MyThread() {
}
/**
* 呼叫父類帶參構造方法
* @param name
*/
public MyThread(String name) {
super(name);
}
MyThread myThread = new MyThread("dog");
MyThread myThread1 = new MyThread("cat");
呼叫父類帶參構造方法直接給執行緒設定名字
三。
通過靜態方法currentThread()獲取當前執行緒名字
System.out.println(Thread.currentThread().getName());
執行緒排程
java使用搶佔式排程模型,優先順序高的執行緒先使用CPU,獲取的cpu時間片(即使用權)相對多一些,如果優先順序一樣,就隨機選擇。
執行緒預設優先順序是5,通過方法getPriority()方法可獲得
執行緒優先順序範圍是1到10
通過方法setPriority()設定優先順序
執行緒優先順序高代表獲取cpu時間片的機率大,不代表一定先執行
執行緒控制
static viod sleep(long millis) 使當前正在執行的執行緒停留指定毫秒數後再執行
void join()等待這個執行緒死亡,等執行join()方法的執行緒執行完畢後再執行下面的其他執行緒
void setDaemon(boolean on) 將此執行緒標記為守護執行緒,當執行的執行緒都是守護執行緒時,java虛擬機器將退出
當主執行緒執行完時,剩下的都是守護執行緒,則不會執行剩下的守護執行緒
Thread.currentThread.setName("main");
這就是主執行緒
如果把其他執行緒設定為守護執行緒時,當主執行緒執行完畢後,守護執行緒將很快執行完畢,不是立即消失
執行緒生命週期
建立執行緒的第二種方法
1.建立一個類MyRunnable實現Runnable介面
2.重寫run()方法
3.建立類MyRunnable的物件
4.建立Thread類的物件,把MyRunnable物件作為構造方法的引數
5.啟動執行緒
public class MyRunnable implements Runnable{
public void run() {
for (int i = 0; i <30 ; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
//建立Runnable類的物件
MyRunnable myRunnable = new MyRunnable();
//建立Thread類的物件,把MyRunnable物件作為構造方法的引數
Thread thread1 = new Thread(myRunnable,"dog");
Thread thread2 = new Thread(myRunnable,"cat");
thread1.start();
thread2.start();
第二種方法實現介面不影響他繼承其他類,第一種方法繼承了Thread之後就不能繼承其他類了,避免了java單繼承的侷限性
第二種方法把myRunnable當作資源,供不同執行緒使用,適合相同程式碼處理同一個資源的情況,把執行緒和程式的程式碼,資料分離,體現面向物件
多執行緒資料安全問題:
是否多執行緒環境
是否有共享資料
是否有多條語句操作共享資料
如何解決多執行緒安全問題:
基本思想:讓程式沒有安全問題的環境
把多條語句操作共享資料的程式碼鎖起來,讓任意時刻只能有一個執行緒執行即可
同步程式碼塊來實現
synchronized(任意物件){
多條語句操作共享資料的程式碼
}
任意物件可以看成是一把鎖,但是任意物件只能是同一個,一把鎖
public class Sell implements Runnable{
private int tickets=100;
//同一把鎖
private Object object=new Object();
public void run() {
while (true){
synchronized (object){
if(tickets>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"張票");
tickets--;
}
}
}
}
}
同步的好處:解決了多執行緒的資料安全問題
弊端:當執行緒很多時,每個執行緒都會去判斷同步上的鎖,很耗費資源,會降低程式的執行效率
同步方法:把synchronized 關鍵字加到方法上 ,把方法內部的程式碼鎖定,this可以代表
同步靜態方法:把synchronized 關鍵字加到靜態方法上 ,把靜態方法內部的程式碼鎖定,用 類名 .class 可以代表
private synchronized void sellTicket(){
if(tickets>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"張票");
tickets--;
}
}
private static synchronized void sellTicket(){
if(tickets>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"張票");
tickets--;
}
}
StringBuffer Vector Hashtable 都執行同步,速度慢,每個執行緒都會去判斷同步上的鎖,很耗費資源,會降低程式的執行效率
為了更清晰的表達如何加鎖和釋放鎖,JDK5以後提供了一個新的鎖物件Lock
Lock實現比使用synchronized方法和語句可以獲得更廣泛的鎖定操作
void lock()獲得鎖
void unlock()釋放鎖
Lock是介面不能直接例項化,採用他的實現類ReentrantLock來例項化
//鎖物件
private Lock lock = new ReentrantLock();
public void run() {
while (true) {
lock.lock();
try {
if (tickets > 0) {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "張票");
tickets--;
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
解鎖放到finally裡,因為之前的程式碼如果出問題的話,最終也會解鎖
Object類中的方法:
wait()導致當前執行緒等待,直到另一個執行緒呼叫該物件的notify()方法或notifyAll()方法
notify()喚醒正在等待物件監視器的單個執行緒
notifyAll()喚醒正在等待物件監視器的所有執行緒