java中的多线程——进度1
import java.util.*;
public static void main(String[] args) {
/*
final可以修飾類,方法,變量。
final修飾的類不可以被繼承。
final修飾的方法不可以被覆蓋。
final修飾的變量是一個(gè)常量。只能被賦值一次。
內(nèi)部類只能訪問被final修飾的局部變量。
*/
/*抽象類和抽象方法
*/
/*
接口
*/
/*try catch
在try塊,catch塊,finally塊和異常塊外存在return語句的情況。finally中的return是會(huì)提前退出的,
finally中的代碼在其他兩塊中中存在return是要運(yùn)行的,只不過不會(huì)改變r(jià)eturn中結(jié)果。
*/
/**
1. 線程定義的兩種方法,
??? ?第一是繼承Thread類并覆蓋run方法,start()方法調(diào)用run()方法開啟線程和任務(wù)。run()方法只是主函數(shù)中的一個(gè)普通方法不會(huì)開啟多線程。由于java不支持多繼承,當(dāng)需要多線程的子類有父類時(shí),可以通過接口的方式實(shí)現(xiàn)多繼承。所以出現(xiàn)第二種方法。
??? ?第二是實(shí)現(xiàn)runable接口,并實(shí)現(xiàn)接口中的run方法,把線程任務(wù)封裝在run方法中,通過Thread類創(chuàng)建線程對(duì)象。
2. 線程中的方法
??? ?調(diào)用當(dāng)前線程:Thread.currentThread().getName();
??? ?start(),stop(),sleep(time),wait(),notify()
??? ?構(gòu)造方法:Thread();Thread(Runnable r)通過Thread的這個(gè)構(gòu)造方法傳遞定義好的Runnable子類接口實(shí)現(xiàn)第二種方法的多線程創(chuàng)建;
?3.線程的狀態(tài)
??? ?cpu的執(zhí)行資格:可以被cpu的處理,在處理隊(duì)列中排隊(duì)
??? ?cpu的執(zhí)行權(quán):正在被cpu的處理
??? ?①被創(chuàng)建,
??? ?②運(yùn)行:具備執(zhí)行資格和執(zhí)行權(quán),
??? ?③凍結(jié):釋放執(zhí)行權(quán)和執(zhí)行資格,
??? ?④消亡:
??? ?⑤臨時(shí)阻塞:具備執(zhí)行資格還不具備執(zhí)行權(quán)
4.線程中的問題
?? ?各線程之間互相不會(huì)干擾
class Thread
{
?? ?private Runnable r;
?? ?Thread()
?? ?{
?? ?}
?? ?Thread(Runnable r)
?? ?{
?? ?this.r = r;
?? ?}
?? ?
?? ?public void run()
?? ?{
?? ??? ?if(r!=null)
?? ??? ?r.run();
?? ?}
?? ?public void start()
?? ?{
?? ??? ?run();//如果實(shí)現(xiàn)子線程類調(diào)用的是子線程中實(shí)現(xiàn)的run方法,子線程中的run()覆蓋了父類Thread中的方法。
?? ?}
}
//第一種創(chuàng)建多線程的方法
class SubThread extends Thread
{
?? ?public void run()
?? ?{
?? ??? ?System.out.println("haha");
?? ?}
}
//第二種創(chuàng)建多線程的方法
//單獨(dú)將任務(wù)封裝起來,按照面向?qū)ο蟮乃枷雽⑷蝿?wù)封裝成對(duì)象,避免了java單繼承的局限性
class ThreadImpl implements Runnable
{
?? ?public void run()
?? ?{
?? ??? ?system.out.println("runnable run");
?? ?}
}
ThreadImpl i = new ThreadImpl();
Thread t = new Thread(i);
t.start();
5.//多線程賣票
public class Ticket extends Thread{
?? ?private? int num = 100;
?? ?//private? static int num = 100;//靜態(tài)變量實(shí)現(xiàn)唯一
?? ?
?? ?public void run(){
?? ?while(true){
?? ??? ?if(num>0){
?? ??? ??? ?system.out.println(Thread.currentThread().getName()+"...."+num--);
?? ??? ?}
?? ?}
?? ?}
}
class ticketDemo{
?? ?public static void main(String[] args){
?? ??? ?Ticket t1 = new Ticket();
?? ??? ?Ticket t2 = new Ticket();
?? ??? ?Ticket t3 = new Ticket();
?? ??? ?Ticket t4 = new Ticket();
?? ??? ?//Ticket t2 = new Ticket();
?? ??? ?//Ticket t3 = new Ticket();
?? ??? ?//Ticket t4 = new Ticket();
?? ??? ?t1.start();
?? ??? ?t2.start();
?? ??? ?t3.start();
?? ??? ?t4.start();
?? ??? ?//t1.start();t1.start();t1.start();t1.start();
?? ?}
}
//多線程賣票,實(shí)現(xiàn)Runnable接口實(shí)現(xiàn)
public class Ticket implements Runnable{
?? ?private? int num = 100;
?? ?//private? static int num = 100;//靜態(tài)變量實(shí)現(xiàn)唯一
?? ?
?? ?public void run(){
?? ??? ?while(true){
?? ??? ??? ?if(num>0){
?? ??? ??? ??? ?system.out.println(Thread.currentThread().getName()+"...."+num--);
?? ??? ??? ?}
?? ??? ?}
?? ?}
}
class ticketDemo{
?? ?public static void main(String[] args){
?? ??? ?Ticket t = new Ticket();//創(chuàng)建一個(gè)線程任務(wù)對(duì)象
?? ??? ?
?? ??? ?Thread t1 = new Thread(t);
?? ??? ?Thread t2 = new Thread(t);
?? ??? ?Thread t3 = new Thread(t);
?? ??? ?Thread t4 = new Thread(t);
?? ??? ?t1.start();
?? ??? ?t2.start();
?? ??? ?t3.start();
?? ??? ?t4.start();
?? ??? ?//t1.start();t1.start();t1.start();t1.start();
?? ?}
}
6.線程中的安全問題:
當(dāng)一個(gè)線程在執(zhí)行操作共享數(shù)據(jù)的多條代碼過程中,其他線程參與了運(yùn)算,就會(huì)導(dǎo)致線程安全問題的產(chǎn)生。
當(dāng)編號(hào)num為1的線程切換為凍結(jié)狀態(tài),有執(zhí)行資格但沒有執(zhí)行權(quán)的時(shí)候。下一個(gè)線程可以運(yùn)行,當(dāng)切換的線程切換過來后,會(huì)出現(xiàn)0號(hào)票的情況,線程安全出現(xiàn)問題。
原因:多個(gè)線程操作共享的數(shù)據(jù);操作共享數(shù)據(jù)的線程代碼有多條;
public void run(){
?? ?private int num = 100;
?? ?public void run(){
?? ??? ?while(true){
?? ??? ??? ?if(num>0)
?? ??? ??? ?{
?? ??? ??? ??? ?try{Thread.sleep(10);}catch(InterruptedException e){}
?? ??? ??? ??? ?System.out.println(Thread.currentThread().getName()+num--);
?? ??? ??? ?}
?? ??? ?}
?? ?}
}
線程安全問題的解決,線程代碼塊的同步(火車上的衛(wèi)生間),由于同步外的線程都要判斷同步鎖,所以相應(yīng)的降低了效率。
同步去前提:同步中必須有多個(gè)線程并使用同一個(gè)鎖
public void run(){
?? ?private int num = 100;
?? ?object obj = new object();
?? ?public void run(){
?? ??? ?while(true){
?? ??? ??? ?synchronize(obj)
?? ??? ??? ?{
?? ??? ??? ?if(num>0)
?? ??? ??? ?{
?? ??? ??? ??? ?try{Thread.sleep(10);}catch(InterruptedException e){}
?? ??? ??? ??? ?System.out.println(Thread.currentThread().getName()+num--);
?? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
?? ?}
}
7.//銀行儲(chǔ)戶的例子
class Bank
{
?? ?private int sum;
?? ?private Object obj = new Object();
?? ?public void add(int num)
?? ?{
?? ??? ?synchronized(obj)//同步代碼塊在調(diào)用的地方。
?? ??? ?{
?? ??? ??? ?sum = sum + num;
?? ??? ??? ?try{Thread.sleep(10);}catch(InterruptedException e){}
?? ??? ??? ?System.out.println("sum="+sum);
?? ??? ?}
?? ?}
}
class Cus implements Runnable
{
?? ?private Bank b = new Bank();
?? ?public void run()
?? ?{
?? ??? ?for(int x=0; x<3;x++)
?? ??? ?{
?? ??? ??? ?b.add(100);
?? ??? ?}
?? ?}
}
//銀行儲(chǔ)戶的例子(同步關(guān)鍵字作為函數(shù)的修飾符)(同步代碼塊到同步函數(shù)的轉(zhuǎn)換)
//同步函數(shù)使用的鎖是this,所以在同步代碼塊和同步函數(shù)混合使用的時(shí)候在同步代碼塊加的鎖為this。
//同步函數(shù)和同步代碼塊的區(qū)別
?? ?1,同步函數(shù)的鎖是固定的this
?? ?2,同步代碼塊是任意的對(duì)象
?? ?3,同步代碼塊的使用較多。
//靜態(tài)同步函數(shù)的鎖
?? ?1,在同步代碼塊加鎖的時(shí)候與同步函數(shù)的區(qū)別
?? ?synchronize(this)
?? ?{
?? ??? ?if(num>0)
?? ??? ?{
?? ??? ??? ?try{Thread.sleep(10);}catch(InterruptException e){}
?? ??? ??? ?System.out.println(Thread.currenThread.getName()+num--);
?? ??? ?}
?? ?}
?? ?2,在同步代碼塊加鎖的時(shí)候與同步函數(shù)的區(qū)別
?? ?靜態(tài)的同步函數(shù)使用的鎖是 該函數(shù)所屬字節(jié)碼文件對(duì)象,
?? ?可以用getClass方法獲取,也可以用當(dāng)前類名.class表示
?? ?synchronize(this.getClass())//this是當(dāng)前票對(duì)象
?? ?{
?? ??? ?if(num>0)
?? ??? ?{
?? ??? ??? ?try{Thread.sleep(10);}catch(InterruptException e){}
?? ??? ??? ?System.out.println(Thread.currenThread.getName()+num--);
?? ??? ?}
?? ?}
class Bank
{
?? ?private int sum;
?? ?private Object obj = new Object();
?? ?public synchronized void add(int num)//同步函數(shù)
?? ?{
//?? ??? ?synchronized(obj)//同步代碼塊在調(diào)用的地方。
?? ?//?? ?{
?? ??? ??? ?sum = sum + num;
?? ??? ??? ?try{Thread.sleep(10);}catch(InterruptedException e){}
?? ??? ??? ?System.out.println("sum="+sum);
?? ?//?? ?}
?? ?}
}
class Cus implements Runnable
{
?? ?private Bank b = new Bank();
?? ?public void run()
?? ?{
?? ??? ?for(int x=0; x<3;x++)
?? ??? ?{
?? ??? ??? ?b.add(100);
?? ??? ?}
?? ?}
}
8.//多線程下的單例設(shè)計(jì)模式
//餓漢式的
class Single
{
?? ?private static final Single s = new Single();
?? ?private Single(){}
?? ?public static Single getInstance()
?? ?{
?? ??? ?return s;
?? ?}
}
//懶漢式
calss Single
{
?? ?private static Single s = null;
?? ?private Single(){}
?? ?public static synchronized Single getInstance()
?? ?{
?? ??? ?if(s==null){//解決效率問題
?? ??? ??? ?synchronized(Single.class){//此處不能用this.getClass()因?yàn)間etclass方法是非靜態(tài)的。
?? ??? ??? ?if(s==null)
?? ??? ??? ?s = new Single();
?? ??? ??? ?}
?? ??? ?}
?? ?}
}
class SingleDemo
{
?? ?public static void main(String[] args)
?? ?{
?? ??? ?System.out.println("hello world!");
?? ?}
}
//枚舉類來實(shí)現(xiàn)
public enum animalHelperSingleton{
INSTANCE;
private AnimalHelperSingleton(){}
public Animal[] buildAnimalList(){
final Animal[] animals = new Animal[10];
animals[0] =new SimpleAnimal(Animal.AnimalClass.MAMMAL, "DOG0", TRUE,COLOR.GRAY);
animals[0] =new SimpleAnimal(Animal.AnimalClass.MAMMAL, "DOG1", TRUE,COLOR.GRAY);
animals[0] =new SimpleAnimal(Animal.AnimalClass.MAMMAL, "DOG2", TRUE,COLOR.GRAY);
animals[0] =new SimpleAnimal(Animal.AnimalClass.MAMMAL, "DOG3", TRUE,COLOR.GRAY);
return animals;
}
}
9.死鎖:代碼塊中的鎖有同步函數(shù)的鎖,同步函數(shù)的鎖中有代碼塊的鎖,兩個(gè)線程每個(gè)拿到一半資源,互不相讓。
死鎖實(shí)例
class Test implements Runnable
{
?? ?private boolean flag;
?? ?Test(boolean flag)
?? ?{
?? ??? ?this.flag = flag;
?? ?}
?? ?public void run()
?? ?{
?? ??? ?if(flag)
?? ??? ?{
?? ??? ??? ?while(true)
?? ??? ??? ?{
?? ??? ??? ??? ?synchronized(MyLock.locka)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?System.out.println(thread.current.getName()+"if?? locaka..");
?? ??? ??? ??? ??? ?synchronized(MyLock.lockb)
?? ??? ??? ??? ??? ?System.out.println(thread.current.getName()+"if?? locakb..");
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
?? ??? ?else
?? ??? ?{
?? ??? ??? ?while(true)
?? ??? ??? ?{
?? ??? ??? ??? ?synchronized(MyLock.lockb)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?System.out.prinln(thread.current.getName()+"else lockb...");
?? ??? ??? ??? ??? ?synchronized(MyLock.locka)
?? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ?System.out.println(thread.current.getName()+"else locka...");
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
?? ?}
}
class MyLock
{
?? ?pbulic static final Object locka = new Object();
?? ?public static final Object lockb = new Object();
}
*/
/**
10.線程通信
多個(gè)線程在處理統(tǒng)一資源,但是任務(wù)不同
等待喚醒機(jī)制? ,wait(),notify(),notifyall()
//資源
class Resource
{
?? ?String name;
?? ?String sex;
?? ?boolean flag = false;
}
//輸入
class Input implements Runnable
{
?? ?Resource r;
?? ?input(Resource r)
?? ?{
?? ??? ?this.r = r;
?? ?}
?? ?public void run()
?? ?{
?? ??? ?int x = 0;
?? ??? ?while(true)
?? ??? ?{
?? ??? ??? ?synchronized(r)
?? ??? ??? ?{
?? ??? ??? ??? ?if(r.flag)
?? ??? ??? ??? ??? ?r.wait();
?? ??? ??? ??? ?if(x==0)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?r.name="mike";
?? ??? ??? ??? ??? ?r.sex="nan";
?? ??? ??? ??? ?}
?? ??? ??? ??? ?else
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?r.name="麗麗";
?? ??? ??? ??? ??? ?r.sex="女女女女女";
?? ??? ??? ??? ?}
?? ??? ??? ??? ?r.flag = true;
?? ??? ??? ??? ?r.notify();
?? ??? ??? ?}
?? ??? ??? ?x = (x+1)%2;
?? ??? ?}
?? ?}
}
//輸出
class Output implements runnable
{
?? ?Resource r;
?? ?Output(Resource r)
?? ?{
?? ??? ?this.r = r;
?? ?}
?? ?public void run()
?? ?{
?? ??? ?while(true)
?? ??? ?{
?? ??? ??? ?synchronized(r)
?? ??? ??? ?{
?? ??? ??? ??? ?if(!flag)
?? ??? ??? ??? ??? ?r.wait();
?? ??? ??? ??? ?System.out.println(r.name+"..."+r.sex);
?? ??? ??? ??? ?r.flag = false;
?? ??? ??? ??? ?r.notify();
?? ??? ??? ?}
?? ??? ?}
?? ?}
}
class RsourceDemo2
{
?? ?public static void main(String[] args)
?? ?{
?? ??? ?//創(chuàng)建資源
?? ??? ?Resource r = new Resource();
?? ??? ?//創(chuàng)建任務(wù)
?? ??? ?Input in = new Input(r);
?? ??? ?Output out = new Output(r);
?? ??? ?//定義線程
?? ??? ?Thread t1 = new Thread(in);
?? ??? ?Thread t2 = new Thread(out);
?? ??? ?//開啟線程
?? ??? ?t1.start();
?? ??? ?t2.start();
?? ?}
}
/*
11.等待喚醒機(jī)制,生產(chǎn)者消費(fèi)者模式
class Resouce
{
?? ?private String name;
?? ?private int count=1;
?? ?private boolean flag = false;
?? ?public void set(String name)
?? ?{
?? ??? ?if(flag)
?? ??? ??? ?try{this.wait();}catch(InterruptedException e){}
?? ??? ?this.name = name+count;
?? ??? ?count++;
?? ??? ?System.out.println(Thread.currentThread().getName()+"...生產(chǎn)者。。。。"+this.name);
?? ??? ?flag = true;
?? ??? ?notify();
?? ?}
?? ?public void out()
?? ?{
?? ??? ?if(flag)
?? ??? ??? ?try{this.wait();}catch(InterruptedException e){}
?? ??? ?System.out.println(Thread.currentThread().getName()+"...消費(fèi)者。。。。。"+this.name);
?? ??? ?flag = false;
?? ??? ?notify();
?? ?}
}
class producer implements Runnable
{
?? ?private Resource r;
?? ?Producer(Resource r)
?? ?{
?? ??? ?this.r = r;
?? ?}
?? ?pbulic void run()
?? ?{
?? ??? ?while(true)
?? ??? ?{
?? ??? ??? ?r.out();
?? ??? ?}
?? ?}
}
class consumer implements Runnable
{
?? ?private Resource r;
?? ?Producer(Resource r)
?? ?{
?? ??? ?this.r = r;
?? ?}
?? ?pbulic void run()
?? ?{
?? ??? ?while(true)
?? ??? ?{
?? ??? ??? ?r.set("烤鴨");
?? ??? ?}
?? ?}
}
class ProducerConsumerDemo
{
?? ?public static void main(String[] args)
?? ?{
?? ??? ?//創(chuàng)建資源
?? ??? ?Resouce r = new Resource();
?? ??? ?//創(chuàng)建任務(wù)
?? ??? ?Producer pro = new Producer();
?? ??? ?Consumer con = new Consumer();
?? ??? ?//創(chuàng)建線程
?? ??? ?Thread t1 = new Thread(pro);
?? ??? ?Thread t2 = new Thread(con);
?? ??? ?//開啟線程
?? ??? ?t1.start();
?? ??? ?t2.start();
?? ?}
}
12.//多生產(chǎn)和多消費(fèi)的問題
class Resouce
{
?? ?private String name;
?? ?private int count=1;
?? ?private boolean flag = false;
?? ?public void set(String name)
?? ?{
?? ??? ?while(flag)//多次判斷,讓阻塞的線程繼續(xù)判斷標(biāo)記,解決了線程獲取執(zhí)行權(quán)后是否要運(yùn)行。
?? ??? ??? ?try{this.wait();}catch(InterruptedException e){}
?? ??? ?this.name = name+count;
?? ??? ?count++;
?? ??? ?System.out.println(Thread.currentThread().getName()+"...生產(chǎn)者。。。。"+this.name);
?? ??? ?flag = true;
?? ??? ?notifyAll();//喚醒所有,解決了死鎖問題。
?? ?}
?? ?public void out()
?? ?{
?? ??? ?while(flag)
?? ??? ??? ?try{this.wait();}catch(InterruptedException e){}
?? ??? ?System.out.println(Thread.currentThread().getName()+"...消費(fèi)者。。。。。"+this.name);
?? ??? ?flag = false;
?? ??? ?notifyAll();
?? ?}
}
class producer implements Runnable
{
?? ?private Resource r;
?? ?Producer(Resource r)
?? ?{
?? ??? ?this.r = r;
?? ?}
?? ?pbulic void run()
?? ?{
?? ??? ?while(true)
?? ??? ?{
?? ??? ??? ?r.out();
?? ??? ?}
?? ?}
}
class consumer implements Runnable
{
?? ?private Resource r;
?? ?Producer(Resource r)
?? ?{
?? ??? ?this.r = r;
?? ?}
?? ?pbulic void run()
?? ?{
?? ??? ?while(true)
?? ??? ?{
?? ??? ??? ?r.set("烤鴨");
?? ??? ?}
?? ?}
}
class ProducerConsumerDemo
{
?? ?public static void main(String[] args)
?? ?{
?? ??? ?//創(chuàng)建資源
?? ??? ?Resouce r = new Resource();
?? ??? ?//創(chuàng)建任務(wù)
?? ??? ?Producer pro = new Producer();
?? ??? ?Consumer con = new Consumer();
?? ??? ?//創(chuàng)建線程
?? ??? ?Thread t1 = new Thread(pro);
?? ??? ?Thread t2 = new Thread(con);
?? ??? ?//開啟線程
?? ??? ?t1.start();
?? ??? ?t2.start();
?? ?}
}
*/
//多生產(chǎn)和多消費(fèi)的問題,由于為了防止多消費(fèi)者和多生產(chǎn)者多線程中的死鎖問題,
//在消費(fèi)者和生產(chǎn)者完成相應(yīng)操作后必須把線程池中阻塞的線程進(jìn)行全部喚醒,這樣會(huì)導(dǎo)致
//一個(gè)問題就是,每次喚醒的線程中會(huì)有本方的線程,雖然通過while判斷進(jìn)行再次wait阻塞并放入線程中
//但是這樣會(huì)浪費(fèi)系統(tǒng)的開銷。所以必須實(shí)現(xiàn)在同一個(gè)鎖中的多個(gè)任務(wù)多線程操作,這樣就引出了同一個(gè)鎖中的多個(gè)監(jiān)視器的感念。
//由于生產(chǎn)者和消費(fèi)者所處的監(jiān)視器可以分開,所以在喚醒操作中,可以實(shí)現(xiàn)只喚醒對(duì)方的線程任務(wù)。
//這個(gè)實(shí)現(xiàn)方法通過java1.5中的新特性,LOCK接口實(shí)現(xiàn) ,通過實(shí)例化lock接口的子類來定義多個(gè)監(jiān)視器。
//condition接口:出現(xiàn)替代了object中的wait,notify notifyAll方法
//?? ??? ??? ??? ?將這些監(jiān)視器方法單獨(dú)進(jìn)行封裝,變成Condition監(jiān)視器對(duì)象。
//?? ??? ??? ??? ?可以任意鎖進(jìn)行組合。
// await(); wait();
// signal(); notify();
// signalAll(); notifyAll();
/*
class Resouce
{
?? ?private String name;
?? ?private int count=1;
?? ?private boolean flag = false;
?? ?//創(chuàng)建一個(gè)鎖對(duì)象
?? ?Lock lock = new();
?? ?//通過已有鎖獲取該鎖上的兩組監(jiān)視器對(duì)象
?? ?Condition producer_con = lock.newcondition();
?? ?condition consumer_con = lock.newCondition();
?? ?public void set(String name)
?? ?{
?? ??? ?while(flag)//多次判斷,讓阻塞的線程繼續(xù)判斷標(biāo)記,解決了線程獲取執(zhí)行權(quán)后是否要運(yùn)行。
?? ??? ??? ?try{producer_con.await();}catch(InterruptedException e){}
?? ??? ?this.name = name+count;
?? ??? ?count++;
?? ??? ?System.out.println(Thread.currentThread().getName()+"...生產(chǎn)者。。。。"+this.name);
?? ??? ?flag = true;
?? ??? ?consumer_con.singleAll();//喚醒所有,解決了死鎖問題。
?? ?}
?? ?public void out()
?? ?{
?? ??? ?while(flag)
?? ??? ??? ?try{consumer_con.await();}catch(InterruptedException e){}
?? ??? ?System.out.println(Thread.currentThread().getName()+"...消費(fèi)者。。。。。"+this.name);
?? ??? ?flag = false;
?? ??? ?consumer_con.singleAll();
?? ?}
}
class producer implements Runnable
{
?? ?private Resource r;
?? ?Producer(Resource r)
?? ?{
?? ??? ?this.r = r;
?? ?}
?? ?pbulic void run()
?? ?{
?? ??? ?while(true)
?? ??? ?{
?? ??? ??? ?r.out();
?? ??? ?}
?? ?}
}
class consumer implements Runnable
{
?? ?private Resource r;
?? ?Producer(Resource r)
?? ?{
?? ??? ?this.r = r;
?? ?}
?? ?pbulic void run()
?? ?{
?? ??? ?while(true)
?? ??? ?{
?? ??? ??? ?r.set("烤鴨");
?? ??? ?}
?? ?}
}
class ProducerConsumerDemo
{
?? ?public static void main(String[] args)
?? ?{
?? ??? ?//創(chuàng)建資源
?? ??? ?Resouce r = new Resource();
?? ??? ?//創(chuàng)建任務(wù)
?? ??? ?Producer pro = new Producer();
?? ??? ?Consumer con = new Consumer();
?? ??? ?//創(chuàng)建線程
?? ??? ?Thread t1 = new Thread(pro);
?? ??? ?Thread t2 = new Thread(con);
?? ??? ?//開啟線程
?? ??? ?t1.start();
?? ??? ?t2.start();
?? ?}
}
*/
}
轉(zhuǎn)載于:https://www.cnblogs.com/jinb/p/6201819.html
總結(jié)
以上是生活随笔為你收集整理的java中的多线程——进度1的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: gRPC源码分析2-Server的建立
- 下一篇: php定时删除文件夹下文件(清理缓存文件