日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

(CZ深入浅出Java基础)线程笔记

發(fā)布時(shí)間:2025/7/14 71 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (CZ深入浅出Java基础)线程笔记 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這是劉意老師的JAVA基礎(chǔ)教程的筆記
講的賊好,附上傳送門

傳智風(fēng)清揚(yáng)-超全面的Java基礎(chǔ)

一、線程的引入

1.多線程概述

  • 進(jìn)程
    a.正在運(yùn)行的程序,是系統(tǒng)進(jìn)行資源分類和調(diào)用的獨(dú)立單位。
    b.每個(gè)進(jìn)程都有它自己的內(nèi)存空間和系統(tǒng)資源。
  • 線程
    a.是進(jìn)程中的單個(gè)順序控制流,是一條執(zhí)行路徑。
    b.一個(gè)進(jìn)程如果只有一條路徑,則稱為單線程程序。
    c.一個(gè)進(jìn)程如果有多條執(zhí)行路徑,則稱為多線程程序。
  • 小結(jié)
    線程多的進(jìn)程搶到CPU執(zhí)行權(quán)的概率大,但是仍具有隨機(jī)性。

2.Java程序運(yùn)行原理

Java命令會(huì)啟動(dòng)Java虛擬機(jī),啟動(dòng)JVM,等于啟動(dòng)了一個(gè)應(yīng)用程序,也就是啟動(dòng)了一個(gè)進(jìn)程。該進(jìn)程會(huì)自動(dòng)啟動(dòng)一個(gè)“主線程”,然后主線程去調(diào)用某個(gè)類的main方法。

3.并發(fā)和并行

  • 并發(fā)
    物理上的同時(shí)發(fā)生,并發(fā)是在同一個(gè)時(shí)間點(diǎn)上同時(shí)發(fā)生。
  • 并行
    邏輯上的同時(shí)發(fā)生,并行是在同一個(gè)時(shí)間段上同時(shí)發(fā)生。

二、線程的使用(方式1)

1.多線程的使用舉例

創(chuàng)建新執(zhí)行線程有兩種方法。一種方法是將類聲明為 Thread 的子類。該子類應(yīng)重寫 Thread 類的 run 方法。接下來(lái)可以分配并啟動(dòng)該子類的實(shí)例。start方法是先啟動(dòng)線程,然后由JVM調(diào)用線程的run方法。

public class Demo {public static void main(String[] args) {// TODO Auto-generated method stubMyThread my1=new MyThread();MyThread my2=new MyThread();my1.start();//啟動(dòng)一個(gè)進(jìn)程my2.start();}}class MyThread extends Thread{@Overridepublic void run() {// TODO Auto-generated method stubfor(int i=0;i<1000;i++){System.out.println(i);}} }

2.線程的基本使用

  • 獲取名稱
public class Demo {public static void main(String[] args) {// TODO Auto-generated method stubMyThread my1 = new MyThread();MyThread my2 = new MyThread();my1.start();my2.start();}}class MyThread extends Thread {@Overridepublic void run() {// TODO Auto-generated method stubfor (int i = 0; i < 1000; i++) {System.out.println(getName() + ":" + i);}} } public class Demo {public static void main(String[] args) {// TODO Auto-generated method stubThread main_thread = Thread.currentThread();System.out.println(main_thread.getName());} }
  • 設(shè)置線程名稱
    可以通過(guò)構(gòu)造函數(shù),也可以通過(guò)setName方法
public class Demo {public static void main(String[] args) {// TODO Auto-generated method stub // MyThread my1 = new MyThread(); // MyThread my2 = new MyThread(); // my1.setName("my1"); // my2.setName("my2");MyThread my1 = new MyThread("my1");MyThread my2 = new MyThread("my2");my1.start();my2.start();}}class MyThread extends Thread {@Overridepublic void run() {// TODO Auto-generated method stubfor (int i = 0; i < 1000; i++) {System.out.println(getName() + ":" + i);}}public MyThread(){super();}public MyThread(String name){super(name);} }
  • 線程調(diào)度
    設(shè)置優(yōu)先級(jí),但是線程優(yōu)先級(jí)也只是標(biāo)識(shí)線程獲得CPU控制權(quán)的幾率高。
public class Demo {public static void main(String[] args) {// TODO Auto-generated method stubMyThread my1 = new MyThread("my1");MyThread my2 = new MyThread("my2");System.out.println(my1.getName()+"---"+my1.getPriority());System.out.println(my2.getName()+"---"+my2.getPriority());my1.setPriority(1);my2.setPriority(10);my1.start();my2.start();}}class MyThread extends Thread {@Overridepublic void run() {// TODO Auto-generated method stubfor (int i = 0; i < 1000; i++) {System.out.println(getName() + ":" + i);}}public MyThread(String name){super(name);}
  • 線程休眠
public class Demo {public static void main(String[] args) {// TODO Auto-generated method stubMyThread my1 = new MyThread("my1");MyThread my2 = new MyThread("my2");my1.start();my2.start();}}class MyThread extends Thread {@Overridepublic void run() {// TODO Auto-generated method stubfor (int i = 0; i < 1000; i++) {System.out.println(getName() + ":" + i);try {Thread.sleep(1000);//這個(gè)異常只能try-catch處理,因?yàn)楦割惖膔un方法沒(méi)有拋出異常,子類重寫方法也不能拋出異常} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}public MyThread(String name){super(name);} }
  • 線程加入
    指的是調(diào)用join方法的線程執(zhí)行完了,下面的程序才能執(zhí)行。
public static void main(String[] args) {// TODO Auto-generated method stubMyThread my1 = new MyThread("my1");MyThread my2 = new MyThread("my2");MyThread my3 = new MyThread("my3");my1.start();try {my1.join();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}my2.start();try {my2.join();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}my3.start();}

join的用法可以參考:java多線程 join方法以及優(yōu)先級(jí)方法,Java多線程中join方法的理解。
(太長(zhǎng)不看版= =:join方法就是要等這個(gè)自己這個(gè)線程走完了,調(diào)用啟動(dòng)自己這個(gè)線程的主線程才能繼續(xù)往下走,其他線程不管,具體的可以試試下面的代碼)

public class Demo {public static void main(String[] args) {MyThread my1 = new MyThread("my1");MyThread my2 = new MyThread("my2");MyThread my3 = new MyThread("my3");my1.start();my2.start();try {my1.join();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}for(int i=0;i<10000;i++){System.out.println("main");}my3.start();} }


大概就這個(gè)意思

  • 線程禮讓
    只能讓線程的執(zhí)行更加和諧,但不能保證絕對(duì)謙讓。
public class Demo {public static void main(String[] args) {MyThread my1 = new MyThread("my1");MyThread my2 = new MyThread("my2");MyThread my3 = new MyThread("my3");my1.start();my2.start();// my3.start();} }class MyThread extends Thread {@Overridepublic void run() {// TODO Auto-generated method stubfor (int i = 0; i < 1000; i++) {System.out.println(getName() + ":" + i);Thread.yield();}}public MyThread(String name) {super(name);} }
  • 守護(hù)線程
    將該線程標(biāo)記為守護(hù)線程或用戶線程。當(dāng)正在運(yùn)行的線程都是守護(hù)線程時(shí),Java 虛擬機(jī)退出。該方法必須在啟動(dòng)線程前調(diào)用。該方法首先調(diào)用該線程的 checkAccess 方法,且不帶任何參數(shù)。這可能拋出 SecurityException(在當(dāng)前線程中)。
    拋出:IllegalThreadStateException - 如果該線程處于活動(dòng)狀態(tài)。
        SecurityException - 如果當(dāng)前線程無(wú)法修改該線程。
public class Demo {public static void main(String[] args) {MyThread my1 = new MyThread("my1");MyThread my2 = new MyThread("my2");MyThread my3 = new MyThread("my3");my1.setDaemon(true);my2.setDaemon(true);my3.setDaemon(true);my1.start();my2.start();my3.start();for(int i=0;i<5;i++){System.out.println("main");}} }
  • 中斷線程
    stop方法已經(jīng)不建議使用了。然而Interupt方法我也沒(méi)太搞懂= =
import java.util.Date;public class Demo {public static void main(String[] args) {MyThread my1 = new MyThread("my1");my1.start();try {Thread.sleep(3000);my1.interrupt();} catch (InterruptedException e) {e.printStackTrace();System.out.println("線程終止");} // my1.stop();} }class MyThread extends Thread {@Overridepublic void run() {System.out.println("開(kāi)始執(zhí)行:" + new Date());try {Thread.sleep(10000);} catch (InterruptedException e) {System.out.println("線程終止");}System.out.println("結(jié)束執(zhí)行:" + new Date());}public MyThread(String name) {super(name);} }

三、線程的狀態(tài)

四、線程的使用(第二種方式)

1.多線程實(shí)現(xiàn)舉例

創(chuàng)建線程的另一種方法是聲明實(shí)現(xiàn) Runnable 接口的類。該類然后實(shí)現(xiàn) run 方法。然后可以分配該類的實(shí)例,在創(chuàng)建 Thread 時(shí)作為一個(gè)參數(shù)來(lái)傳遞并啟動(dòng)。

public class Demo {public static void main(String[] args) {MyRunnable my=new MyRunnable();Thread t1=new Thread(my);Thread t2=new Thread(my);t1.start();t2.start();} }class MyRunnable implements Runnable {@Overridepublic void run() {// TODO Auto-generated method stubfor (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName() + ":" + i);}} }

2.那為什么還要有第二種方法呢?

  • 避免了java單繼承帶來(lái)的局限性。簡(jiǎn)單來(lái)說(shuō)就是我已經(jīng)有一個(gè)父類了,那我想實(shí)現(xiàn)多線程就不能在繼承另一個(gè)父類了。
  • 適合多個(gè)相同程序的代碼去處理同一個(gè)資源的情況,線程是線程,程序代碼是程序代碼,數(shù)據(jù)有效分離開(kāi),降低耦合度。體現(xiàn)面向?qū)ο蟮乃枷搿?/strong>

五、線程的同步性

1.線程同步性概念的引入

還是在模擬賣票的情景中,三個(gè)窗口賣一百?gòu)埰?#xff0c;這三個(gè)窗口要共享這一百?gòu)埰钡馁Y源。如果運(yùn)用如下程序,則兩個(gè)線程各自從100輸出到1,一共輸出了200行。

public class Demo1 {public static void main(String[] args) {MyThread my1=new MyThread();MyThread my2=new MyThread();my1.start();my2.start();} }class MyThread extends Thread{static int x=100;//加靜態(tài)修飾符@Overridepublic void run() {// TODO Auto-generated method stubfor(;x>0;x--){//標(biāo)記點(diǎn)1System.out.println(getName()+":"+x);//標(biāo)記點(diǎn)2}} }

然而我們發(fā)現(xiàn),上面的代碼結(jié)果確實(shí)好了一些,但是還是會(huì)偶爾出現(xiàn)“賣同一張票”(就是一個(gè)數(shù)字輸出多次),甚至?xí)霈F(xiàn)輸出負(fù)數(shù)0。這是為什么呢?原因其實(shí)都是:程序的執(zhí)行具有原子性,并且線程的執(zhí)行是具有隨機(jī)性的。當(dāng)線程1到達(dá)標(biāo)記點(diǎn)1的時(shí)候,可能線程2也到達(dá)了標(biāo)記點(diǎn)1,然后當(dāng)線程1到達(dá)標(biāo)記點(diǎn)2的時(shí)候,線程1已經(jīng)輸出了一個(gè)x(比如說(shuō)是100),但是還沒(méi)來(lái)得及進(jìn)行x--操作,這時(shí)候cpu資源假如被線程2搶走,執(zhí)行了輸出語(yǔ)句,這時(shí)候由于x--還沒(méi)有執(zhí)行,因此輸出的還是100,所以即使是static了,也有可能輸出兩個(gè)一樣的數(shù)字,甚至x--也是兩個(gè)原子操作,先返回一個(gè)x,然后進(jìn)行x=x-1,可能在線程1執(zhí)行返回一個(gè)i之后,線程2把資源搶跑了,這時(shí)候i的值還是沒(méi)有變化。出現(xiàn)負(fù)數(shù)的愿意也是同理,假如現(xiàn)在兩個(gè)線程都到了標(biāo)記1并且x現(xiàn)在等于1,然后線程1開(kāi)始執(zhí)行,假設(shè)已經(jīng)執(zhí)行完了x--操作,那么這個(gè)時(shí)候x就是0了,然后線程2開(kāi)始走,這時(shí)候線程2輸出的就0了。
上面的代碼即使運(yùn)用接口的方法創(chuàng)建線程,也有可能出現(xiàn)相同的情況。
考慮多線程的數(shù)據(jù)安全問(wèn)題:1.是否是多線程環(huán)境。2.是否有共享數(shù)據(jù)。3.是否有多條數(shù)據(jù)操作共享數(shù)據(jù)。

2.同步機(jī)制

2.1.synchronized

  • 2.1.1.synchronized代碼塊
    synchronized修飾的代碼,在一個(gè)線程進(jìn)行的時(shí)候,發(fā)現(xiàn)這段代碼已經(jīng)上了鎖,其他線程不能執(zhí)行。
public class Demo {public static void main(String[] args) {MyRunnable my = new MyRunnable();Thread t1 = new Thread(my);Thread t2 = new Thread(my);t1.start();t2.start();} }class MyRunnable implements Runnable {int x = 100;Object obj = new Object();@Overridepublic void run() {synchronized (obj) {for (; x > 0; x--) {System.out.println(Thread.currentThread().getName() + ":" + x);}}} }

同步代碼塊的傳入對(duì)象可以是任意對(duì)象。

public class Demo {public static void main(String[] args) {MyRunnable my = new MyRunnable();Thread t1 = new Thread(my);Thread t2 = new Thread(my);t1.start();t2.start();} }class MyRunnable implements Runnable {int x = 1000;Object obj1 = new Object();Object obj2 = new Object();int a = 0;@Overridepublic void run() {if (a % 2 == 0) {synchronized (obj1) {for (; x > 0; x--) {System.out.println(Thread.currentThread().getName() + ":" + x);}}}else{synchronized (obj2) {for (; x > 0; x--) {System.out.println(Thread.currentThread().getName() + ":" + x);}}}a++;} }

上面這塊代碼也沒(méi)出問(wèn)題,但是我沒(méi)明白,明明不是同一個(gè)鎖啊,為什么還沒(méi)出問(wèn)題?

  • 2.1.2.synchronized方法
    同步方法的默認(rèn)鎖對(duì)象是this。靜態(tài)方法的默認(rèn)鎖是當(dāng)前對(duì)象的類對(duì)象(.class對(duì)象)。
@Overridepublic synchronized void run() {for (; x > 0; x--) {System.out.println(Thread.currentThread().getName() + ":" + x);}}

2.2.Lock鎖
Lock 實(shí)現(xiàn)提供了比使用 synchronized 方法和語(yǔ)句可獲得的更廣泛的鎖定操作。

public class Demo {public static void main(String[] args) {MyRunnable st = new MyRunnable();Thread t1 = new Thread(st);Thread t2 = new Thread(st);Thread t3 = new Thread(st);t1.start();t2.start();t3.start();} }class MyRunnable implements Runnable {int tickets = 100;Lock lock = new ReentrantLock();@Overridepublic void run() {lock.lock();try {//解決出現(xiàn)如果異常則鎖放不開(kāi)的問(wèn)題for (; tickets > 0;) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ":" + tickets--);}} finally {lock.unlock();}} }

2.3 死鎖問(wèn)題
指兩個(gè)或者兩個(gè)以上的線程在執(zhí)行過(guò)程中因爭(zhēng)奪資源而產(chǎn)生的一種互相等待的現(xiàn)象。

public class Demo {public static void main(String[] args) {Thread t1 = new DeadLock(true);Thread t2 = new DeadLock(false);t1.start();t2.start();} }class MyLock{public static final Object objA=new Object();public static final Object objB=new Object(); }class DeadLock extends Thread{boolean flag;public DeadLock(boolean flag){this.flag=flag;}@Overridepublic void run() {if(flag){synchronized(MyLock.objA){System.out.println("if objA");synchronized(MyLock.objB){System.out.println("if objB");}}}else{synchronized(MyLock.objB){System.out.println("else objA");synchronized(MyLock.objA){System.out.println("else objB");}}}} }

2.4.等待喚醒機(jī)制
public final void wait(long timeout) throws InterruptedException
在其他線程調(diào)用此對(duì)象的 notify() 方法或 notifyAll() 方法,或者超過(guò)指定的時(shí)間量前,導(dǎo)致當(dāng)前線程等待。
當(dāng)前線程必須擁有此對(duì)象監(jiān)視器。

此方法導(dǎo)致當(dāng)前線程(稱之為 T)將其自身放置在對(duì)象的等待集中,然后放棄此對(duì)象上的所有同步要求。出于線程調(diào)度目的,在發(fā)生以下四種情況之一前,線程 T 被禁用,且處于休眠狀態(tài):

其他某個(gè)線程調(diào)用此對(duì)象的 notify 方法,并且線程 T 碰巧被任選為被喚醒的線程。
其他某個(gè)線程調(diào)用此對(duì)象的 notifyAll 方法。
其他某個(gè)線程中斷線程 T。
大約已經(jīng)到達(dá)指定的實(shí)際時(shí)間。但是,如果 timeout 為零,則不考慮實(shí)際時(shí)間,在獲得通知前該線程將一直等待。
然后,從對(duì)象的等待集中刪除線程 T,并重新進(jìn)行線程調(diào)度。然后,該線程以常規(guī)方式與其他線程競(jìng)爭(zhēng),以獲得在該對(duì)象上同步的權(quán)利;一旦獲得對(duì)該對(duì)象的控制權(quán),該對(duì)象上的所有其同步聲明都將被恢復(fù)到以前的狀態(tài),這就是調(diào)用 wait 方法時(shí)的情況。然后,線程 T 從 wait 方法的調(diào)用中返回。所以,從 wait 方法返回時(shí),該對(duì)象和線程 T 的同步狀態(tài)與調(diào)用 wait 方法時(shí)的情況完全相同。

在沒(méi)有被通知、中斷或超時(shí)的情況下,線程還可以喚醒一個(gè)所謂的虛假喚醒 (spurious wakeup)。雖然這種情況在實(shí)踐中很少發(fā)生,但是應(yīng)用程序必須通過(guò)以下方式防止其發(fā)生,即對(duì)應(yīng)該導(dǎo)致該線程被提醒的條件進(jìn)行測(cè)試,如果不滿足該條件,則繼續(xù)等待。換句話說(shuō),等待應(yīng)總是發(fā)生在循環(huán)中。

public final void notify()

喚醒在此對(duì)象監(jiān)視器上等待的單個(gè)線程。如果所有線程都在此對(duì)象上等待,則會(huì)選擇喚醒其中一個(gè)線程。選擇是任意性的,并在對(duì)實(shí)現(xiàn)做出決定時(shí)發(fā)生。線程通過(guò)調(diào)用其中一個(gè) wait 方法,在對(duì)象的監(jiān)視器上等待。
例如,喚醒的線程在作為鎖定此對(duì)象的下一個(gè)線程方面沒(méi)有可靠的特權(quán)或劣勢(shì)。
此方法只應(yīng)由作為此對(duì)象監(jiān)視器的所有者的線程來(lái)調(diào)用。通過(guò)以下三種方法之一,線程可以成為此對(duì)象監(jiān)視器的所有者:

通過(guò)執(zhí)行此對(duì)象的同步實(shí)例方法。
通過(guò)執(zhí)行在此對(duì)象上進(jìn)行同步的 synchronized 語(yǔ)句的正文。
對(duì)于 Class 類型的對(duì)象,可以通過(guò)執(zhí)行該類的同步靜態(tài)方法。

public class Demo {public static void main(String[] args) {Student s = new Student();SetStudent st = new SetStudent(s);GetStudent gt = new GetStudent(s);Thread t1 = new Thread(st);Thread t2 = new Thread(gt);t1.start();t2.start();} }class Student {int age;String name;boolean flag; }class SetStudent implements Runnable {Student s;int x;SetStudent(Student s) {this.s = s;}@Overridepublic void run() {for (;; x++) {synchronized (s) {if (s.flag) {try {s.wait();} catch (InterruptedException e) {e.printStackTrace();}}if (x % 2 == 0) {s.name = "zzz";s.age = 23;} else {s.name = "xxx";s.age = 55;}s.flag = true;s.notify();// 喚醒t2,但是喚醒不一定立即執(zhí)行,還要進(jìn)行CPU執(zhí)行權(quán)的爭(zhēng)奪。}}} }class GetStudent implements Runnable {Student s;int x;GetStudent(Student s) {this.s = s;}@Overridepublic void run() {for (;;) {synchronized (s) {if (!s.flag) {try {s.wait();// t2等待了, 立即釋放鎖,醒過(guò)來(lái)的時(shí)候從這里醒來(lái)。} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(s.name + ":" + s.age);s.flag = false;s.notify();}}} }

六、線程組

1.線程組的概述和使用

public class Demo {public static void main(String[] args) {method1();method2();}static void method1(){MyRunnable my=new MyRunnable();Thread t1=new Thread(my);Thread t2=new Thread(my);ThreadGroup tg1=t1.getThreadGroup();ThreadGroup tg2=t2.getThreadGroup();System.out.println(tg1.getName()+"---"+tg2.getName());}static void method2(){MyRunnable my=new MyRunnable();ThreadGroup tg=new ThreadGroup("這是一個(gè)新的組");Thread t1=new Thread(tg,my);Thread t2=new Thread(tg,my);System.out.println(t1.getThreadGroup().getName()+"---"+t2.getThreadGroup().getName());} }class MyRunnable implements Runnable{@Overridepublic void run() {for(int x=0;x<100;x++){System.out.println(Thread.currentThread().getName()+":"+x);}} }

七、線程池

1.概述和使用

程序啟動(dòng)一個(gè)新線程成本是比較高的,因?yàn)樗婕暗揭c操作系統(tǒng)進(jìn)行交互。而使用線程池可以很好的提高性能,尤其是當(dāng)程序中要?jiǎng)?chuàng)建大量生存期很短的線程時(shí),更應(yīng)該考慮使用線程池。

線程池里的每一個(gè)線程代碼結(jié)束后,并不會(huì)死亡,而是再次回到線程池中成為空閑狀態(tài),等待下一個(gè)對(duì)象來(lái)使用。

在JDK5之前,我們必須手動(dòng)實(shí)現(xiàn)自己的線程池,從JDK5開(kāi)始,Java內(nèi)置支持線程池。

public class Demo {public static void main(String[] args) {ExecutorService pool=Executors.newFixedThreadPool(2);pool.submit(new MyRunnable());pool.submit(new MyRunnable());pool.shutdown();} }class MyRunnable implements Runnable{@Overridepublic void run() {for(int x=0;x<100;x++){System.out.println(Thread.currentThread()+":"+x);}} }

2.線程的實(shí)現(xiàn)(第三種方法)

public interface Callable<V>

返回結(jié)果并且可能拋出異常的任務(wù)。實(shí)現(xiàn)者定義了一個(gè)不帶任何參數(shù)的叫做 call 的方法。Callable 接口類似于 Runnable,兩者都是為那些其實(shí)例可能被另一個(gè)線程執(zhí)行的類設(shè)計(jì)的。但是 Runnable 不會(huì)返回結(jié)果,并且無(wú)法拋出經(jīng)過(guò)檢查的異常。

public interface Future<V>

Future 表示異步計(jì)算的結(jié)果。它提供了檢查計(jì)算是否完成的方法,以等待計(jì)算的完成,并獲取計(jì)算的結(jié)果。計(jì)算完成后只能使用 get 方法來(lái)獲取結(jié)果,如有必要,計(jì)算完成前可以阻塞此方法。取消則由 cancel 方法來(lái)執(zhí)行。還提供了其他方法,以確定任務(wù)是正常完成還是被取消了。一旦計(jì)算完成,就不能再取消計(jì)算。如果為了可取消性而使用 Future 但又不提供可用的結(jié)果,則可以聲明 Future<?> 形式類型、并返回 null 作為底層任務(wù)的結(jié)果。

public class Demo {public static void main(String[] args) throws InterruptedException, ExecutionException {ExecutorService pool=Executors.newFixedThreadPool(2);Future<Integer> f1=pool.submit(new MyCallable(100));Future<Integer> f2=pool.submit(new MyCallable(200));Integer i1=f1.get();Integer i2=f2.get();System.out.println(i1+":"+i2);pool.shutdown();} } class MyCallable implements Callable<Integer>{int number;public MyCallable(int number) {this.number=number;}@Overridepublic Integer call() throws Exception {int sum=0;for(int x=0;x<number;x++){sum+=x;}return sum;} }

八、匿名內(nèi)部類實(shí)現(xiàn)多線程

public class Demo {public static void main(String[] args){new Thread(){@Overridepublic void run() {for(int x=0;x<100;x++){System.out.println(Thread.currentThread().getName()+"---"+x);}}}.start();new Thread(new Runnable(){@Overridepublic void run() {for(int x=0;x<100;x++){System.out.println(Thread.currentThread().getName()+"---"+x);}}}).start();new Thread(new Runnable(){@Overridepublic void run() {for(int x=0;x<100;x++){System.out.println("hello---"+x);}}}){@Overridepublic void run() {for(int x=0;x<100;x++){System.out.println("world---"+x);}}}.start();} }

九、定時(shí)器

1.概述和使用

定時(shí)器是一個(gè)應(yīng)用十分廣泛的線程工具,可用于調(diào)度多個(gè)定時(shí)任務(wù)以后臺(tái)線程的方式執(zhí)行。在Java中,可以通過(guò)Timer和TimerTask類來(lái)實(shí)現(xiàn)定義調(diào)度的功能。

Timer

一種工具,線程用其安排以后在后臺(tái)線程中執(zhí)行的任務(wù)??砂才湃蝿?wù)執(zhí)行一次,或者定期重復(fù)執(zhí)行。
與每個(gè) Timer 對(duì)象相對(duì)應(yīng)的是單個(gè)后臺(tái)線程,用于順序地執(zhí)行所有計(jì)時(shí)器任務(wù)。計(jì)時(shí)器任務(wù)應(yīng)該迅速完成。如果完成某個(gè)計(jì)時(shí)器任務(wù)的時(shí)間太長(zhǎng),那么它會(huì)“獨(dú)占”計(jì)時(shí)器的任務(wù)執(zhí)行線程。因此,這就可能延遲后續(xù)任務(wù)的執(zhí)行,而這些任務(wù)就可能“堆在一起”,并且在上述不友好的任務(wù)最終完成時(shí)才能夠被快速連續(xù)地執(zhí)行。

TimerTask

由 Timer 安排為一次執(zhí)行或重復(fù)執(zhí)行的任務(wù)。

public class Demo{public static void main(String[] args){Timer t=new Timer();t.schedule(new MyTask(), 3000);t.schedule(new MyTask(t), 6000);t.schedule(new MyTask(), 9000,200);}}class MyTask extends TimerTask{Timer t;public MyTask() {}public MyTask(Timer t){this.t=t;}@Overridepublic void run() {System.out.println("BANG!");} }

總結(jié)

以上是生活随笔為你收集整理的(CZ深入浅出Java基础)线程笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。