java中的多线程——进度1
import java.util.*;
public static void main(String[] args) {
/*
final可以修飾類,方法,變量。
final修飾的類不可以被繼承。
final修飾的方法不可以被覆蓋。
final修飾的變量是一個常量。只能被賦值一次。
內部類只能訪問被final修飾的局部變量。
*/
/*抽象類和抽象方法
*/
/*
接口
*/
/*try catch
在try塊,catch塊,finally塊和異常塊外存在return語句的情況。finally中的return是會提前退出的,
finally中的代碼在其他兩塊中中存在return是要運行的,只不過不會改變return中結果。
*/
/**
1. 線程定義的兩種方法,
??? ?第一是繼承Thread類并覆蓋run方法,start()方法調用run()方法開啟線程和任務。run()方法只是主函數中的一個普通方法不會開啟多線程。由于java不支持多繼承,當需要多線程的子類有父類時,可以通過接口的方式實現多繼承。所以出現第二種方法。
??? ?第二是實現runable接口,并實現接口中的run方法,把線程任務封裝在run方法中,通過Thread類創建線程對象。
2. 線程中的方法
??? ?調用當前線程:Thread.currentThread().getName();
??? ?start(),stop(),sleep(time),wait(),notify()
??? ?構造方法:Thread();Thread(Runnable r)通過Thread的這個構造方法傳遞定義好的Runnable子類接口實現第二種方法的多線程創建;
?3.線程的狀態
??? ?cpu的執行資格:可以被cpu的處理,在處理隊列中排隊
??? ?cpu的執行權:正在被cpu的處理
??? ?①被創建,
??? ?②運行:具備執行資格和執行權,
??? ?③凍結:釋放執行權和執行資格,
??? ?④消亡:
??? ?⑤臨時阻塞:具備執行資格還不具備執行權
4.線程中的問題
?? ?各線程之間互相不會干擾
class Thread
{
?? ?private Runnable r;
?? ?Thread()
?? ?{
?? ?}
?? ?Thread(Runnable r)
?? ?{
?? ?this.r = r;
?? ?}
?? ?
?? ?public void run()
?? ?{
?? ??? ?if(r!=null)
?? ??? ?r.run();
?? ?}
?? ?public void start()
?? ?{
?? ??? ?run();//如果實現子線程類調用的是子線程中實現的run方法,子線程中的run()覆蓋了父類Thread中的方法。
?? ?}
}
//第一種創建多線程的方法
class SubThread extends Thread
{
?? ?public void run()
?? ?{
?? ??? ?System.out.println("haha");
?? ?}
}
//第二種創建多線程的方法
//單獨將任務封裝起來,按照面向對象的思想將任務封裝成對象,避免了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;//靜態變量實現唯一
?? ?
?? ?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();
?? ?}
}
//多線程賣票,實現Runnable接口實現
public class Ticket implements Runnable{
?? ?private? int num = 100;
?? ?//private? static int num = 100;//靜態變量實現唯一
?? ?
?? ?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();//創建一個線程任務對象
?? ??? ?
?? ??? ?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.線程中的安全問題:
當一個線程在執行操作共享數據的多條代碼過程中,其他線程參與了運算,就會導致線程安全問題的產生。
當編號num為1的線程切換為凍結狀態,有執行資格但沒有執行權的時候。下一個線程可以運行,當切換的線程切換過來后,會出現0號票的情況,線程安全出現問題。
原因:多個線程操作共享的數據;操作共享數據的線程代碼有多條;
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--);
?? ??? ??? ?}
?? ??? ?}
?? ?}
}
線程安全問題的解決,線程代碼塊的同步(火車上的衛生間),由于同步外的線程都要判斷同步鎖,所以相應的降低了效率。
同步去前提:同步中必須有多個線程并使用同一個鎖
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.//銀行儲戶的例子
class Bank
{
?? ?private int sum;
?? ?private Object obj = new Object();
?? ?public void add(int num)
?? ?{
?? ??? ?synchronized(obj)//同步代碼塊在調用的地方。
?? ??? ?{
?? ??? ??? ?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);
?? ??? ?}
?? ?}
}
//銀行儲戶的例子(同步關鍵字作為函數的修飾符)(同步代碼塊到同步函數的轉換)
//同步函數使用的鎖是this,所以在同步代碼塊和同步函數混合使用的時候在同步代碼塊加的鎖為this。
//同步函數和同步代碼塊的區別
?? ?1,同步函數的鎖是固定的this
?? ?2,同步代碼塊是任意的對象
?? ?3,同步代碼塊的使用較多。
//靜態同步函數的鎖
?? ?1,在同步代碼塊加鎖的時候與同步函數的區別
?? ?synchronize(this)
?? ?{
?? ??? ?if(num>0)
?? ??? ?{
?? ??? ??? ?try{Thread.sleep(10);}catch(InterruptException e){}
?? ??? ??? ?System.out.println(Thread.currenThread.getName()+num--);
?? ??? ?}
?? ?}
?? ?2,在同步代碼塊加鎖的時候與同步函數的區別
?? ?靜態的同步函數使用的鎖是 該函數所屬字節碼文件對象,
?? ?可以用getClass方法獲取,也可以用當前類名.class表示
?? ?synchronize(this.getClass())//this是當前票對象
?? ?{
?? ??? ?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)//同步函數
?? ?{
//?? ??? ?synchronized(obj)//同步代碼塊在調用的地方。
?? ?//?? ?{
?? ??? ??? ?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.//多線程下的單例設計模式
//餓漢式的
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()因為getclass方法是非靜態的。
?? ??? ??? ?if(s==null)
?? ??? ??? ?s = new Single();
?? ??? ??? ?}
?? ??? ?}
?? ?}
}
class SingleDemo
{
?? ?public static void main(String[] args)
?? ?{
?? ??? ?System.out.println("hello world!");
?? ?}
}
//枚舉類來實現
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.死鎖:代碼塊中的鎖有同步函數的鎖,同步函數的鎖中有代碼塊的鎖,兩個線程每個拿到一半資源,互不相讓。
死鎖實例
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.線程通信
多個線程在處理統一資源,但是任務不同
等待喚醒機制? ,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)
?? ?{
?? ??? ?//創建資源
?? ??? ?Resource r = new Resource();
?? ??? ?//創建任務
?? ??? ?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.等待喚醒機制,生產者消費者模式
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()+"...生產者。。。。"+this.name);
?? ??? ?flag = true;
?? ??? ?notify();
?? ?}
?? ?public void out()
?? ?{
?? ??? ?if(flag)
?? ??? ??? ?try{this.wait();}catch(InterruptedException e){}
?? ??? ?System.out.println(Thread.currentThread().getName()+"...消費者。。。。。"+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)
?? ?{
?? ??? ?//創建資源
?? ??? ?Resouce r = new Resource();
?? ??? ?//創建任務
?? ??? ?Producer pro = new Producer();
?? ??? ?Consumer con = new Consumer();
?? ??? ?//創建線程
?? ??? ?Thread t1 = new Thread(pro);
?? ??? ?Thread t2 = new Thread(con);
?? ??? ?//開啟線程
?? ??? ?t1.start();
?? ??? ?t2.start();
?? ?}
}
12.//多生產和多消費的問題
class Resouce
{
?? ?private String name;
?? ?private int count=1;
?? ?private boolean flag = false;
?? ?public void set(String name)
?? ?{
?? ??? ?while(flag)//多次判斷,讓阻塞的線程繼續判斷標記,解決了線程獲取執行權后是否要運行。
?? ??? ??? ?try{this.wait();}catch(InterruptedException e){}
?? ??? ?this.name = name+count;
?? ??? ?count++;
?? ??? ?System.out.println(Thread.currentThread().getName()+"...生產者。。。。"+this.name);
?? ??? ?flag = true;
?? ??? ?notifyAll();//喚醒所有,解決了死鎖問題。
?? ?}
?? ?public void out()
?? ?{
?? ??? ?while(flag)
?? ??? ??? ?try{this.wait();}catch(InterruptedException e){}
?? ??? ?System.out.println(Thread.currentThread().getName()+"...消費者。。。。。"+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)
?? ?{
?? ??? ?//創建資源
?? ??? ?Resouce r = new Resource();
?? ??? ?//創建任務
?? ??? ?Producer pro = new Producer();
?? ??? ?Consumer con = new Consumer();
?? ??? ?//創建線程
?? ??? ?Thread t1 = new Thread(pro);
?? ??? ?Thread t2 = new Thread(con);
?? ??? ?//開啟線程
?? ??? ?t1.start();
?? ??? ?t2.start();
?? ?}
}
*/
//多生產和多消費的問題,由于為了防止多消費者和多生產者多線程中的死鎖問題,
//在消費者和生產者完成相應操作后必須把線程池中阻塞的線程進行全部喚醒,這樣會導致
//一個問題就是,每次喚醒的線程中會有本方的線程,雖然通過while判斷進行再次wait阻塞并放入線程中
//但是這樣會浪費系統的開銷。所以必須實現在同一個鎖中的多個任務多線程操作,這樣就引出了同一個鎖中的多個監視器的感念。
//由于生產者和消費者所處的監視器可以分開,所以在喚醒操作中,可以實現只喚醒對方的線程任務。
//這個實現方法通過java1.5中的新特性,LOCK接口實現 ,通過實例化lock接口的子類來定義多個監視器。
//condition接口:出現替代了object中的wait,notify notifyAll方法
//?? ??? ??? ??? ?將這些監視器方法單獨進行封裝,變成Condition監視器對象。
//?? ??? ??? ??? ?可以任意鎖進行組合。
// await(); wait();
// signal(); notify();
// signalAll(); notifyAll();
/*
class Resouce
{
?? ?private String name;
?? ?private int count=1;
?? ?private boolean flag = false;
?? ?//創建一個鎖對象
?? ?Lock lock = new();
?? ?//通過已有鎖獲取該鎖上的兩組監視器對象
?? ?Condition producer_con = lock.newcondition();
?? ?condition consumer_con = lock.newCondition();
?? ?public void set(String name)
?? ?{
?? ??? ?while(flag)//多次判斷,讓阻塞的線程繼續判斷標記,解決了線程獲取執行權后是否要運行。
?? ??? ??? ?try{producer_con.await();}catch(InterruptedException e){}
?? ??? ?this.name = name+count;
?? ??? ?count++;
?? ??? ?System.out.println(Thread.currentThread().getName()+"...生產者。。。。"+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()+"...消費者。。。。。"+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)
?? ?{
?? ??? ?//創建資源
?? ??? ?Resouce r = new Resource();
?? ??? ?//創建任務
?? ??? ?Producer pro = new Producer();
?? ??? ?Consumer con = new Consumer();
?? ??? ?//創建線程
?? ??? ?Thread t1 = new Thread(pro);
?? ??? ?Thread t2 = new Thread(con);
?? ??? ?//開啟線程
?? ??? ?t1.start();
?? ??? ?t2.start();
?? ?}
}
*/
}
轉載于:https://www.cnblogs.com/jinb/p/6201819.html
總結
以上是生活随笔為你收集整理的java中的多线程——进度1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: gRPC源码分析2-Server的建立
- 下一篇: 使用while循环输入 1 2 3 4