java多線程學(xué)習(xí)總結(jié)
Posted on 2009-03-05 20:49 鄭舒力 閱讀(1764) 評論(1) 編輯 收藏 所屬分類: J2SE 學(xué)習(xí)筆記小弟的第二篇j2se學(xué)習(xí)筆記,如果有錯誤或者遺漏的地方,還懇請各位高手老鳥們不要見笑,多給小弟一些批評,建議!
一、線程的基本概念
簡單的說:線程就是一個程序里不同的執(zhí)行路徑
在同一個時(shí)間點(diǎn)上cpu只會有一個線程在執(zhí)行
Java里的多線程是通過java.lang.Thread類來實(shí)現(xiàn)的
每個線程都擁有自己獨(dú)立的方法??臻g
二、java線程的創(chuàng)建和啟動
第一種
定義線程類實(shí)現(xiàn)Runnable接口
Thread myThread = new Thread(target) //target為Runnable接口類型
Runnable中只有一個方法:
public void run();用以定義線程運(yùn)行體
第二種
可以定義一個Thread的子類并重寫其run方法:
clas MyThread extends Thread{
public void run(){}
}
線程類必須通過執(zhí)行Thread的start()方法啟動一個新的線程
如果調(diào)用run()方法是屬于方法的調(diào)用,不會啟動一個新的線程
推薦使用第一種方式創(chuàng)建線程,使用接口較為靈活
二、線程狀態(tài)裝換
調(diào)用線程start()方法時(shí),線程進(jìn)入就緒狀態(tài),Cpu分配時(shí)間片,線程進(jìn)入運(yùn)行狀態(tài)
時(shí)間片結(jié)束,run()方法未執(zhí)行完,線程進(jìn)入阻塞狀態(tài)。
三、線程控制基本方法
isAlive() //判斷線程是否還“活著”,即線程是否還未終止
getPriority() //獲得線程的優(yōu)先級數(shù)值
setPriority() //設(shè)置線程的優(yōu)先級指數(shù)
Thread.sleep() //靜態(tài)方法,將當(dāng)前線程睡眠指定毫秒數(shù)
join() //調(diào)用某線程的該方法,將當(dāng)前線程與該線程合并,
//即等待該線程結(jié)束,再回復(fù)當(dāng)前線程的運(yùn)行。
yield() //讓出CPU,當(dāng)前線程進(jìn)入就緒狀態(tài)等待調(diào)度
interrupt() //中斷線程
wait() //當(dāng)前線程進(jìn)入對象的wait pool
notify()/all //喚醒對象的wait pool中的一個/所有等待線程
四、sleep方法
Thread的靜態(tài)方法
public static void sleep(long millis)throws InterruptedException
必須對異常進(jìn)行捕捉
Thread.currentThread(); //拿到當(dāng)前線程
五、interrupt方法一種讓線程退出的方式。
public class TestInterrupt{
public static void main(String[] args){
MyThread t = new MyThread();
t.start();
try{Thread.sleep(10000);}
catch(InterruptedException i){}
t.interrupt();
}
}
class MyThread extends Thread{
public void run(){
while(true){
try{
System.out.println("------"+new Date()+"-----");
Thread.sleep(1000);
}catch(InterruptedException i){
return;
}
}
}
}
六、join和yield方法
t.join(); //t的run()方法完才會繼續(xù)執(zhí)行當(dāng)前線程方法體
//也就是兩個線程變成了一個線程
t.yield(); //暫停當(dāng)前正在執(zhí)行的線程對象,并執(zhí)行其他線程。方法為靜態(tài)
//哪個線程體執(zhí)行此方法,哪個線程讓步
public static void main(String[] args) {
MyThread3 t1 = new MyThread3("t1");
MyThread3 t2 = new MyThread3("t2");
t1.start(); t2.start();
}
}
class MyThread3 extends Thread {
MyThread3(String s){super(s);}
public void run(){
for(int i =1;i<=100;i++){
System.out.println(getName()+": "+i);
if(i%10==0){
yield();
}
}
}
}
七、線程優(yōu)先級別
線程的優(yōu)先級用數(shù)字表示,范圍從1到10,一個線程的缺省優(yōu)先級為5.
Thread.MAX_PRIORITY=1
Thread.MIN_PRIORITY=10
Thread.NORM_PRIORITY=5
例:t.setPriority(Thread.NORM_PRIORITY+3);
★八、線程同步
1.同步代碼塊
synchronized(this){ //在執(zhí)行代碼塊過程中,不會被其他線程打斷
...
}
public sunchronized void method //執(zhí)行此方法時(shí),當(dāng)前對象被鎖定
在Java語言中,引入了對象互斥鎖的概念,保證共享數(shù)據(jù)操作的完整性,每個對象 都對應(yīng)一個可稱為"互斥鎖"的標(biāo)記,這個標(biāo)記保證在任一時(shí)刻,只能有一個線程訪 問該對象。
2.線程死鎖
public int flag = 1;
static Object o1 = new Object(), o2 = new Object();
public void run() {
System.out.println("flag=" + flag);
if(flag == 1) {
synchronized(o1) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized(o2) {
System.out.println("1");
}
}
}
if(flag == 0) {
synchronized(o2) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized(o1) {
System.out.println("0");
}
}
}
}
public static void main(String[] args) {
TestDeadLock td1 = new TestDeadLock();
TestDeadLock td2 = new TestDeadLock();
td1.flag = 1;
td2.flag = 0;
Thread t1 = new Thread(td1);
Thread t2 = new Thread(td2);
t1.start();
t2.start();
}
}
九、生產(chǎn)者消費(fèi)者問題
public static void main(String[] args) {
SyncStack ss = new SyncStack();
Producer p = new Producer(ss);
Consumer c = new Consumer(ss);
new Thread(p).start();
new Thread(p).start();
new Thread(p).start();
new Thread(c).start();
}
}
class WoTou {
int id;
WoTou(int id) {
this.id = id;
}
public String toString() {
return "WoTou : " + id;
}
}
class SyncStack { //棧實(shí)現(xiàn)
int index = 0;
WoTou[] arrWT = new WoTou[6]; //相當(dāng)于裝物品的籃子
public synchronized void push(WoTou wt) { //生產(chǎn)物品,線程安全
while(index == arrWT.length) { //當(dāng)籃子滿了線程等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll(); //開始生產(chǎn)時(shí),叫醒等待的其他線程開始消費(fèi)
arrWT[index] = wt;
index ++;
}
public synchronized WoTou pop() { //消費(fèi)物品,線程安全
while(index == 0) { //如果籃子空了
try {
this.wait(); //線程等待,等待生產(chǎn)者開始 //生產(chǎn),叫醒此線程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll(); //消費(fèi)時(shí)喊醒生產(chǎn)者生產(chǎn)
index--;
return arrWT[index];
}
}
class Producer implements Runnable { //生產(chǎn)者類
SyncStack ss = null;
Producer(SyncStack ss) {
this.ss = ss;
}
public void run() {
for(int i=0; i<20; i++) { //生產(chǎn)20個
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println("生產(chǎn)了:" + wt);
try {
Thread.sleep((int)(Math.random() * 200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
SyncStack ss = null;
Consumer(SyncStack ss) {
this.ss = ss;
}
public void run() {
for(int i=0; i<20; i++) { //消費(fèi)20個
WoTou wt = ss.pop();
System.out.println("消費(fèi)了: " + wt);
try {
Thread.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}