1. 程式人生 > 其它 >概述執行緒、執行緒建立

概述執行緒、執行緒建立

多執行緒詳解

1.1 概述 執行緒介紹

  • 多工

吃飯玩手機,開車打點滴,蹲坑打遊戲

現實中太多這樣同時做多件事情的例子了,看起來是多個任務都在做,其實本質上我們的大腦在同一時間依舊只做了一件事情。

  • 多執行緒

    道路窄,拓寬,多條路

    收銀,多個收銀員

  • 程式 程序(process) 執行緒(thread)

    • 說起程序,就不得不說下程式。程式是指令和資料的有序集合,其本身沒有任何執行的含義,是—個靜態的概念。

    • 程序則是執行程式的一次執行過程,它是一個動態的概念。 是系統資源分配的單位

    • 通常在一個程序中可以包含若干個執行緒,當然一個程序中至少有一個執行緒,不然沒有存在的意義。執行緒是CPU排程和執行的的單位。

◆執行緒就是獨立的執行路徑;

◆在程式執行時,即使沒有自己建立執行緒,後臺也會有多個執行緒,如主執行緒,gc執行緒(垃圾回收); main()稱之為主執行緒,為系統的入口,用於執行整個程式;

◆在一個程序中,如果開闢了多個執行緒,執行緒的執行由排程器安排排程,排程器是與作業系統緊密相關的,先後順序是不能人為的干預的。

◆對同一份資源操作時,會存在資源搶奪的問題,需要加入併發控制;

◆執行緒會帶來額外的開銷,如cpu排程時間,併發控制開銷。

◆每個執行緒在自己的工作記憶體互動,記憶體控制不當會造成資料不一致

1.2 執行緒建立

三種建立方式

Thread:

package com.zishi.lensson1;

//建立執行緒方式一:繼承Thread類,重寫run()方法,呼叫start開啟執行緒
public class TestThread1 extends Thread{

@Override
public void run() {
//run方法執行緒體
for (int i = 0; i < 20; i++) {
System.out.println("我在摸魚-----"+i);
}
}

public static void main(String[] args) {

//mian執行緒,主執行緒
//建立一個執行緒物件
TestThread1 testThread1 = new TestThread1();

//呼叫start()方法開啟執行緒
testThread1.start();


for (int i = 0; i < 1000; i++) {
System.out.println("我在學習多執行緒"+i);
}

}
}

start()方法 同時進行

testThread1.run();

先執行run()執行緒

網圖下載

package com.zishi.lensson1;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;

//練習Thread,實現多執行緒同步下載圖片
public class TestThread2 extends Thread{

private String url;//網路圖片地址
private String name;//儲存的檔名

public TestThread2(String url, String name) {
this.url = url;
this.name = name;
}

//下載圖片執行緒的執行體
@Override
public void run() {
WebDownloader webDownloader = new WebDownloader();
webDownloader.downloader(url,name);
System.out.println("下載了檔名為:"+name);
}

public static void main(String[] args) {
TestThread2 t1 = new TestThread2("https://pic1.zhimg.com/v2-56e7df4fe56e37c2c4d2478d946cd9b8_b.jpg", "1.jpg");
TestThread2 t2 = new TestThread2("https://pic2.zhimg.com/v2-d7be668fc1616710f55070f4c7cbd081_b.jpg", "2.jpg");
TestThread2 t3 = new TestThread2("https://pic3.zhimg.com/v2-e193c36c5e2809399ccc1cc0e15b1d52_b.jpg", "3.jpg");
t1.start();
t2.start();
t3.start();
}
}

//下載器
class WebDownloader{
//下載方法
public void downloader(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO異常,downloader方法出錯");
}
}
}

Runnable:

package com.zishi.lensson1;

//建立執行緒方式2: 實現Runnable介面,重寫run方法,
//執行執行緒需要丟入runnable介面實現類,呼叫start方法
public class TestThread3 implements Runnable{
@Override
public void run() {
//run方法執行緒體
for (int i = 0; i < 200; i++) {
System.out.println("我在摸魚------"+i);
}
}

public static void main(String[] args) {
//建立runnable介面實現類物件
TestThread3 testThread3 = new TestThread3();

//建立執行緒物件,通過執行緒物件來開啟我們的執行緒,代理
// Thread thread = new Thread(testThread3);
// thread.start();

new Thread(testThread3).start();

for (int i = 0; i < 1000; i++) {
System.out.println("我在學習多執行緒---"+i);
}
}
}

start() 同步進行

Thread 實現了 Runnale

//建立執行緒物件,通過執行緒物件來開啟我們的執行緒,代理
// Thread thread = new Thread(testThread3);
// thread.start();

推薦使用Runnable介面

同一個物件被多執行緒使用 例子:

package com.zishi.lensson1;

//多執行緒同時操作同一個物件
//買火車票的例子
public class TestThread4 implements Runnable{

//票數
private int ticketNums = 10;


@Override
public void run() {
while (true){
if (ticketNums<=0){
break;
}
//模擬延時
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"票");
}
}

public static void main(String[] args) {
TestThread4 testThread4 = new TestThread4();

new Thread(testThread4,"小明").start();
new Thread(testThread4,"小黃").start();
new Thread(testThread4,"黃牛").start();
}
}

案例:龜兔賽跑

package com.zishi.lensson1;

//模擬龜兔賽跑
public class Race implements Runnable{

//勝利者
private static String winner;

@Override
public void run() {
for (int i = 0; i <= 100; i++) {

//模擬兔子休息
if (Thread.currentThread().getName().equals("兔子") && i%10==0){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

//判斷比賽是否結束
boolean flag = gameOver(i);

//如果比賽結束了,就停止程式
if (flag){
break;
}
System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步");
}
}
//判斷是否完成比賽
private boolean gameOver(int steps){
//判斷是否有勝利者
if (winner!=null){
return true;
}{
if (steps>=100){
winner = Thread.currentThread().getName();
System.out.println("winner is "+winner);
return true;
}
}
return false;
}

public static void main(String[] args) {
Race race = new Race();

new Thread(race,"兔子").start();
new Thread(race,"烏龜").start();
}
}