線程
線程是進(jìn)程中的一個單一順序的執(zhí)行單元,也被稱為輕量進(jìn)程(lightweight process)。線程有自己的必須資源擎椰,同時與其他線程進(jìn)程共享全部資源。同一個進(jìn)程中创肥,線程是并發(fā)執(zhí)行的达舒。由于線程的之間的相互制約,線程有就緒叹侄、阻塞巩搏、運行、結(jié)束等狀態(tài)趾代。
java中的線程
在java中運行一個線程很簡單贯底,通過繼承Thread或者實現(xiàn)Runnable接口就可以創(chuàng)建一個線程。
class MyThread exends Thread{
@Override
public void run(){
}
}
class MyRunnable implements Runnable{
@Override
public void run(){
}
}
啟動一個線程
public static void main(String agrs[]){
new MyThread().start();//繼承啟動
new Thread(new MyRunnable()).start();//接口啟動
}
驗證java線程的并發(fā)性
在各自的run方法中 for循環(huán)輸出 各自的名稱
for(int i=0;i<100;i++){
System.out.println("this is implements Runnable");
}
for(int i=0;i<100;i++){
System.out.println("this is extends Thread");
}
線程鎖
下面方法執(zhí)行后,數(shù)據(jù)少于1w
public static void ThreadMuliteTest() throws InterruptedException {
final List<String> list=new ArrayList();
for(int i=0;i<10000;i++){
new Thread(new Runnable() {
@Override
public void run() {
list.add(Thread.currentThread().getName());
}
}).start();
}
console.info("等20s");
Thread.sleep(20000);
System.out.println(list.size());
}
線程如果同時執(zhí)行就會產(chǎn)生一個問題 他們看到list里的數(shù)據(jù)是一樣多的撒强,插入的時候就會互相抵掉對方插入的數(shù)據(jù)禽捆,解決辦法是排隊,加鎖
public static void ThreadMuliteTest() throws InterruptedException {
final List<String> list=new ArrayList();
for(int i=0;i<10000;i++){
new Thread(new Runnable() {
@Override
public void run() {
synchronized (list) {
list.add(Thread.currentThread().getName());
}
}
}).start();
}
console.info("等20s");
Thread.sleep(20000);
System.out.println(list.size());
}
死鎖
當(dāng)線程互相等待對方釋放自己需要的資源時 就會產(chǎn)生死鎖
public static void diedLock(){
Object lock1=new Object();
Object lock2=new Object();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock1){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2){
console.info("運行了飘哨!");
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock2){
synchronized (lock1){
console.info("運行了睦擂!");
}
}
}
}).start();
}
java線程的狀態(tài)
線程狀態(tài)圖
- NEW 新建狀態(tài)
new 之后 start之前 都是屬于NEW狀態(tài),一旦狀態(tài)變成其他 則不會再回到NEW狀態(tài) - BLOCKED 阻塞狀態(tài)
如果獲取不到鎖 則進(jìn)入阻塞狀態(tài) 直到獲取到鎖之后 - RUNNABLE 執(zhí)行狀態(tài)
在run方法里的時候 線程處于執(zhí)行狀態(tài) 一旦run方法結(jié)束 則狀態(tài)不再是執(zhí)行狀態(tài) - WAITING 等待狀態(tài)
wait調(diào)用后杖玲,睡眠不參與搶鎖 等待notify喚醒 - TIMED_WAITING 等待超時狀態(tài)
當(dāng)調(diào)用wait(long timeout)方法時 線程處于等待狀態(tài) 超時后并不返回 而是等待獲取鎖后返回 - TERMINATED 結(jié)束狀態(tài)
在run方法結(jié)束后線程處于結(jié)束狀態(tài)
public static void stateTest() throws InterruptedException {
Thread t=new Thread(new Runnable() {
@Override
public void run() {
long startTime=System.nanoTime();
/**
* Thread.currentThread() 獲取當(dāng)前線程
* Thread.currentThread()===t true
* 打印當(dāng)前線程狀態(tài)
*/
printThreadState(Thread.currentThread());
synchronized (lock){
try {
lock.wait();//放棄搶鎖 處于WATING狀態(tài)
} catch (InterruptedException e) {
e.printStackTrace();
}
}
console.info(System.nanoTime()-startTime+"納秒");
}
});
printThreadState(t);//查看new之后的thread狀態(tài)
synchronized (lock) {
t.start();
while (true) {
printThreadState(t);//查看thread狀態(tài)
if (t.getState() == Thread.State.TERMINATED) {
break;
} else if (t.getState() == Thread.State.TIMED_WAITING) {
synchronized (lock) {
Thread.sleep(20000);
}
} else if (t.getState() == Thread.State.WAITING) {
synchronized (lock) {
lock.notify();//通知wait的線程 醒來搶鎖
}
} else if(t.getState()== Thread.State.BLOCKED){
lock.wait(100);//喚醒阻塞的線程
continue;
}
Thread.sleep(100);//休眠100ms
}
}
}
喚醒線程
當(dāng)線程處于TIMED_WAITING狀態(tài)的時候 可以調(diào)用interrupt喚醒它* NEW 新建狀態(tài)
public static void awakeThread() throws InterruptedException {
Thread t=new Thread(new Runnable() {
@Override
public void run() {
long startTime=System.currentTimeMillis();
try {
synchronized (lock) {
lock.wait(20000);//Thread.sleep(20000) thread.join() lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
console.info("喚醒成功顿仇!"+(System.currentTimeMillis()-startTime)+"s");
}
});
t.start();
Thread.sleep(100);
t.interrupt();
}