Day10(多線程)


多線程

Thread類

 package cn.ljy.myproject01;
 /**
  * @Author liu
  * @Date 2021/11/25 10:35
  * @Description 測試Thread類證明線程不一定立即執行
  * 創建線程方式一:繼承Thread類,重寫run()方法,調用start()來開啟線程
  * @Since version-1.0
  */
 
 public class TextThread extends Thread{
     //重寫線程的run方法
     @Override
     public void run() {
         for (int i = 0; i < 20; i++) {
             System.out.println("我在學習多線程!");
        }
    }
 
     public static void main(String[] args) {
         //main線程,主線程(也就是用戶線程)
         //創建一個線程對象
         TextThread t = new TextThread();
         t.start();//調用start()來開啟線程
 
 
         for (int i = 0; i < 2000; i++) {
             System.out.println("我在打代碼!");
        }
    }
 }
 

 

Runnable接口

 package cn.ljy.myproject01;
 /**
  * @Author liu
  * @Date 2021/11/25 11:21
  * @Description 創建多線程的第二種方式:實現Runnable接口
  * @Since version-1.0
  */
 public class TestRunnable implements Runnable{
 
     @Override
     public void run() {
         for (int i = 0; i < 20; i++) {
             System.out.println("我在學習多線程!"+i);
        }
    }
 
     public static void main(String[] args) {
         TestRunnable t = new TestRunnable();
         t.run();//只是單純的運行的那個t這個類的程序。並沒有做到同時進行
         new Thread(t).start();//同時進行
         for (int i = 0; i < 200; i++) {
             System.out.println("我在打代碼!!"+i);
        }
    }
 }
 
  • 與Thread不同的是需要傳入目標對象+Thread對象.start(),才可以開啟線程。

 

龜兔賽跑

 package cn.ljy.myproject01;
 
 public class Race implements Runnable{
     private static String Winter ;//聲明一個勝利者
     @Override
     public void run() {//重寫一個run方法跑100步
         for (int i = 1; i <= 100; i++) {
             if (Thread.currentThread().getName().equals("兔子")&&i==50 ){
                 try {
                     Thread.sleep(1);
                } catch (InterruptedException e) {
                     e.printStackTrace();
                }
            }
             System.out.println(Thread.currentThread().getName() + "-->第" + i + "步");
             boolean flag = GameOver(i);//調用GameOver方法來進行比賽的判斷
 
             if (flag){
                 break;
            }
        }
    }
     /**
      * @Author liu
      * @Date 2021/11/25 20:14
      * @Description 定義一個比賽結束的判斷當有勝利者的時候結束,當跑到第100步的時候結束,其余情況不結束。
      * @Param [step]
      * @Return java.lang.Boolean
      * @Since version-1.0
      */
     private Boolean GameOver(int step) {
         if (Winter != null) {
             return true;
        }{if(step>=100){
             Winter =Thread.currentThread().getName();
             System.out.println("勝利者:"+Winter);
             return true;
        }
 
        }return  false;
    }
     //主線程運行線程
     public static void main(String[] args) {
         Race race = new Race();
         new Thread(race,"兔子").start();
         new Thread(race,"烏龜").start();
 
    }
 
 
 }
 

Callable

 package cn.ljy.myproject01;
 
 import java.util.concurrent.*;
 
 //創建線程的第三種方法
 public class TestCallable implements Callable<String> {
     private static String Winter ;//聲明一個勝利者
     @Override
     public String call() {//重寫一個run方法跑100步
         for (int i = 1; i <= 100; i++) {
             if (Thread.currentThread().getName().equals("兔子")&&i==50 ){
                 try {
                     Thread.sleep(1);
                } catch (InterruptedException e) {
                     e.printStackTrace();
                }
            }
             System.out.println(Thread.currentThread().getName() + "-->第" + i + "步");
             boolean flag = GameOver(i);//調用GameOver方法來進行比賽的判斷
 
             if (flag){
                 break;
            }
        }return null;
    }
     /**
      * @Author liu
      * @Date 2021/11/25 20:14
      * @Description 定義一個比賽結束的判斷當有勝利者的時候結束,當跑到第100步的時候結束,其余情況不結束。
      * @Param [step]
      * @Return java.lang.Boolean
      * @Since version-1.0
      */
     private Boolean GameOver(int step) {
         if (Winter != null) {
             return true;
        }{if(step>=100){
             Winter =Thread.currentThread().getName();
             System.out.println("勝利者:"+Winter);
             return true;
        }
 
        }return  false;
    }
 
     public static void main(String[] args) throws ExecutionException, InterruptedException {
         TestCallable t1 = new TestCallable();
         //創建執行服務(創建池:需要多少的線程寫多少)
         ExecutorService ser = Executors.newFixedThreadPool(2);
         //提交執行
         Future<String> r = ser.submit(t1);
         Future<String> t = ser.submit(t1);
         //獲取結果
         String rabbit =r.get();
         String tortoise =t.get();
 
         //關閉服務
         ser.shutdownNow();
 
    }
 }
 

Lambda

 package cn.ljy.myproject01;
 /**
  * @Author liu
  * @Date 2021/11/27 22:08
  * @Description 推導lambda表達式
  * @Since version-1.0
  */
 public class TestLambda {
     //3.靜態內部類(要加static)
     static class Like2 implements ILike{
 
         @Override
         public void lambda() {
             System.out.println("i like lambda2!");
        }
    }
     public static void main(String[] args) {
         //普通類的實例(使用接口聲明)
         ILike like = new Like();
         like.lambda();
         //靜態內部類的實例
         like = new Like2();
         like.lambda();
         //4.局部內部類
         class Like3 implements ILike{
 
             @Override
             public void lambda() {
                 System.out.println("i like lambda3!");
            }
        }
         //局部內部類的實例
         like = new Like3();
         like.lambda();
         //5.匿名內部類(沒有類的名字,接住接口來進行實例化)
         like = new ILike() {
             @Override
             public void lambda() {
                 System.out.println("i like lambda4!");
            }
        };
         like.lambda();
         //6.使用lambda表達式
         like=()->{
             System.out.println("i like lambda5!");
        };
         like.lambda();
    }
 }
 //1.創建一個函數式接口
 interface ILike{
     void lambda();
 }
 //2.實現類(實現這個接口的類)
 class Like implements ILike{
 
     @Override
     public void lambda() {
         System.out.println("i like lambda1!");
    }
 }
  • lambda表達式使用情況:接口為函數式接口的時候才可以使用

  • lambda表達式可以繼續進行簡化:

    • 1.簡化掉參數類型(什么類型都可以去掉):變量類型要都去掉的的時候才可以使用,有一個沒去掉就不可以去掉變量類型。

    • 2.簡化掉括號():將函數類型都去掉的時候可以去掉括號,為多個參數的時必須要加上括號

    • 3.簡化掉花括號{}:必須要方法體為一的情況下才可以去掉花括號

線程方法

setPriority(int newPriority):更改線程優先級

static void sleep(long millis):指定毫秒是讓線程休眠

void join():強制插隊(先完成插隊的線程在進行)

static void yield():(也就是禮讓,但禮讓不一定會成功看cpu心情)暫停當前正在執行的線程對象,並執行其他線程。

boolean isAlive():查看線程是否存活

currentThread():返回對當前正在執行的線程對象的引用。

proiority:線程的優先級

 

stop()

 package cn.ljy.myproject01;
 
 public class TestStop implements Runnable{
     //1.設置一個標志位
     Boolean flag = true;
     @Override
     public void run() {
         int i = 0;
         while(flag){
             System.out.println("I+" + i++);
        }
    }
     //2.設置一個公共方法停止線程,標志位轉換
     public  void stop(){
         this.flag=false;
    }
 
 
     public static void main(String[] args) {
         TestStop testStop = new TestStop();
         new Thread(testStop).start();
         for (int i = 0; i < 1000; i++) {
             System.out.println("mian"+i);
             if(i == 900){
                 testStop.stop();
                 System.out.println("已被停止");
            }
        }
    }
 }
 

Sleep

 package cn.ljy.myproject01;
 
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
 public class TestSleep {
     public static void main(String[] args) throws InterruptedException {
         //打印當前系統時間
         Date startTime = new Date(System.currentTimeMillis());//獲取系統當前時間
         while(true){
             Thread.sleep(1000);
             System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
             startTime = new Date(System.currentTimeMillis());//更新當前時間
        }
    }
     public static void tenDown() throws InterruptedException {
 
 
 
         int i=10;
         while(true){
 
             System.out.println(i--);
             Thread.sleep(1000);
             if (i<=0)
                 break;
        }
 
    }
 }
 
  • 每個對象都有一把鎖,sleep不會釋放鎖

Join()

 package cn.ljy.myproject01;
 
 public class TestJoin implements Runnable {
 
     @Override
     public void run() {
         for (int i = 0; i < 100; i++) {
             System.out.println("我是vip");
        }
    }
 
     public static void main(String[] args) throws InterruptedException {
         //啟動我們的線程
         TestJoin testJoin = new TestJoin();
         Thread thread = new Thread(testJoin);
 
         //thread.sleep(5000);
 
         for (int i=0;i<500;i++){
             if (i==100){
                 thread.start();
                 thread.join();//插隊,讓正在運行的線程停下來等待要插隊的線程完成后,在繼續完成剛剛在運行的線程
            }
 
             System.out.println("Main"+i);
 
        }
    }
 }
 

State

image-20211130105727593

package cn.ljy.myproject01;
/**
* @Author liu
* @Date 2021/11/30 10:43
* @Description 觀測線程的狀態
* @Since version-1.0
*/
public class TestState {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("/////////");
});

//觀察狀態
Thread.State state = thread.getState();
System.out.println(state);
//觀察啟動后
thread.start();//啟動線程
state = thread.getState();
System.out.println(state);//Run

while(state !=Thread.State.TERMINATED){
Thread.sleep(100);
state = thread.getState();//更新線程狀態
System.out.println(state);//輸出狀態
}
}
}

優先級

package cn.ljy.myproject01;

import sun.awt.windows.ThemeReader;

public class TestPriority {
public static void main(String[] args) {
//主線程默認優先級
System.out.println(Thread.currentThread().getName()+"->"+Thread.currentThread().getPriority());//打印出主線程的名字
//和主線程的優先級
MyPriority myPriority = new MyPriority();
Thread t1 = new Thread(myPriority);
Thread t2 = new Thread(myPriority);
Thread t3= new Thread(myPriority);
Thread t4 = new Thread(myPriority);
Thread t5 = new Thread(myPriority);
Thread t6 = new Thread(myPriority);

//設置優先級啟動線程
t1.start();

t2.setPriority(Thread.MAX_PRIORITY);
t2.start();

t3.setPriority(1);
t3.start();

t4.setPriority(4);
t4.start();
}


}
class MyPriority implements Runnable{

@Override
public void run() {
//打印出當前正在運行的線程的名字和優先級
System.out.println(Thread.currentThread().getName()+"->"+Thread.currentThread().getPriority());

}
}

deamon

守護線程等用戶線程結束直接結束。

package cn.ljy.myproject01;
//設置守護線程
//上帝守護你
public class TestDaemon {
public static void main(String[] args) {
God god = new God();
Your you = new Your();

Thread thread = new Thread(god);
thread.setDaemon(true);//默認是false表示是用戶線程,正常的都是用戶線程


thread.start();//上帝線程啟動

new Thread(you).start();//用戶線程啟動

}
}
class God implements Runnable{
@Override
public void run() {
while(true){
System.out.println("上帝會保佑你");
}
}
}
class Your implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("開心的或者");
}
System.out.println("----============Goodbye! world!
--------============");

}
}

線程的的不安全問題

package cn.ljy.myproject01;
//不安全的買票
//線程不安全會產生負數
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket ticketEr = new BuyTicket();

new Thread(ticketEr,"me").start();
new Thread(ticketEr,"you").start();
new Thread(ticketEr,"yellow").start();

}
}
class BuyTicket implements Runnable{
private int ticketNum = 10;
boolean flag = true;//線程停止的標志
@Override
public void run() {
//買票
while(flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
private void buy() throws InterruptedException {
//判斷是否有票
if(ticketNum <= 0){
flag = false;

}
Thread.sleep(1000);//延遲讓結果更加明顯
System.out.println(Thread.currentThread().getName() + "拿到" + ticketNum--);
}
}

解決不安全問題

package cn.ljy.myproject01;

//不安全的買票
//線程不安全會產生負數
public class TestSynchronized {
public static void main(String[] args) {
BuyTicket1 ticketEr = new BuyTicket1();

new Thread(ticketEr,"me").start();
new Thread(ticketEr,"you").start();
new Thread(ticketEr,"yellow").start();

}
}
class BuyTicket1 implements Runnable{
private int ticketNum = 10;
boolean flag = true;//線程停止的標志
@Override
public void run() {
//買票
while(flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
private synchronized void buy() throws InterruptedException {
//判斷是否有票
if(ticketNum <= 0){
flag = false;
return;
}
// Thread.sleep(1000);//延遲讓結果更加明顯
System.out.println(Thread.currentThread().getName() + "拿到" + ticketNum--);
}
}
  • 使用synchronized將方法鎖住。

  • 使用synchronized(Obj){}將對象鎖住。Obj稱為同步監視器

DeadLock(死鎖)

package cn.ljy.thread;

import sun.awt.windows.ThemeReader;
//死鎖:多個線程互相抱有資源,然后形成僵直
public class DeadLock {
public static void main(String[] args) {
Makeup t1 = new Makeup(0,"小白");
Makeup t2 = new Makeup(1,"小紅");

t1.start();
t2.start();
}




}

//口紅
class Lipstick{

}

//鏡子
class Mirror{
}
class Makeup extends Thread{
//需要一份鏡子和口紅
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();

int choice;//選擇
String girlName;

Makeup(int choice ,String girlName){
this.choice = choice;
this.girlName = girlName;
}

@Override
public void run() {
//化妝
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void makeup() throws InterruptedException {
if(choice==0){
synchronized (lipstick) {
System.out.println(this.girlName+"獲得口紅");
Thread.sleep(1000);

}synchronized(mirror){
System.out.println(this.girlName+"獲得鏡子");
}

}
else{
synchronized (mirror){
System.out.println(this.girlName+"獲得鏡子");
Thread.sleep(2000);

}synchronized (lipstick){
System.out.println(this.girlName+"獲得口紅");
}

}
}
}

notifyAll(),wait() 管程流

package cn.ljy.thread.gaoji;
//測試生產者和消費者模型,----》利用緩沖區來進行,管程法
//生產者,消費者,產品,緩沖區
public class TestPc {
public static void main(String[] args) {
synContainer container = new synContainer();

new Producer(container).start();
new Consumer(container).start();
}
}
//生產者
class Producer extends Thread{
synContainer container;
public Producer(synContainer container){
this.container=container;
}

@Override
public void run() {
for (int i = 1; i <=20 ; i++) {
try {
container.push(new Chicken(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("生產"+i+"雞");

}
}
}
//消費者
class Consumer extends Thread{
synContainer container;
public Consumer(synContainer container){
this.container=container;
}

@Override
public void run() {
for (int i = 1; i <=20; i++) {
try {
System.out.println("買了"+container.pop().id+"雞");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//產品
class Chicken{
int id;//產品編號
public Chicken(int id){
this.id = id;
}
}
//緩沖區
class synContainer{
//需要一個容器大小
Chicken[] chickens = new Chicken[9];
int count = 0;
//生產者放入產品
public synchronized void push(Chicken chicken) throws InterruptedException {
//如果容器滿了,就叫消費者來進行消費。
if(count==chickens.length){
//通知消費消費,生產者等待
this.wait();
}
//如果容器沒有滿的話,將產品放進容器
chickens[count]=chicken;
count++;
//通知購買
this.notifyAll();
}
//消費者取出產品
public synchronized Chicken pop() throws InterruptedException {
//判官是否有產品消費
if(count==0){
//消費者等待
this.wait();
}
//如果可以進行消費
count--;
Chicken chicken=chickens[count];
//叫生產者生產
this.notifyAll();
return chicken;
}
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM