成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

(CZ深入淺出Java基礎(chǔ))線程筆記

harryhappy / 1781人閱讀

摘要:一個進程如果有多條執(zhí)行路徑,則稱為多線程程序。這可能拋出在當前線程中??紤]多線程的數(shù)據(jù)安全問題是否是多線程環(huán)境。當前線程必須擁有此對象監(jiān)視器。此方法導致當前線程稱之為將其自身放置在對象的等待集中,然后放棄此對象上的所有同步要求。

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

傳智風清揚-超全面的Java基礎(chǔ)

一、線程的引入 1.多線程概述

進程
a.正在運行的程序,是系統(tǒng)進行資源分類和調(diào)用的獨立單位。
b.每個進程都有它自己的內(nèi)存空間和系統(tǒng)資源。

線程
a.是進程中的單個順序控制流,是一條執(zhí)行路徑。
b.一個進程如果只有一條路徑,則稱為單線程程序。
c.一個進程如果有多條執(zhí)行路徑,則稱為多線程程序。

小結(jié)
線程多的進程搶到CPU執(zhí)行權(quán)的概率大,但是仍具有隨機性。

2.Java程序運行原理

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

3.并發(fā)和并行

并發(fā)
物理上的同時發(fā)生,并發(fā)是在同一個時間點上同時發(fā)生。

并行
邏輯上的同時發(fā)生,并行是在同一個時間段上同時發(fā)生。

二、線程的使用(方式1) 1.多線程的使用舉例

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

public class Demo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MyThread my1=new MyThread();
        MyThread my2=new MyThread();
        my1.start();//啟動一個進程
        my2.start();
    }

}

class MyThread extends Thread{
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for(int i=0;i<1000;i++){
            System.out.println(i);
        }
    }
}
2.線程的基本使用

獲取名稱

public class Demo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MyThread my1 = new MyThread();
        MyThread my2 = new MyThread();
        my1.start();
        my2.start();
    }

}

class MyThread extends Thread {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 1000; i++) {
            System.out.println(getName() + ":" + i);
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Thread main_thread = Thread.currentThread();
        System.out.println(main_thread.getName());
    }
}

設(shè)置線程名稱
可以通過構(gòu)造函數(shù),也可以通過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 {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (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)先級,但是線程優(yōu)先級也只是標識線程獲得CPU控制權(quán)的幾率高。

public class Demo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        MyThread 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 {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (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 stub
        
        MyThread my1 = new MyThread("my1");
        MyThread my2 = new MyThread("my2");
        
        my1.start();
        my2.start();
    }

}

class MyThread extends Thread {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 1000; i++) {
            System.out.println(getName() + ":" + i);
            try {
                Thread.sleep(1000);//這個異常只能try-catch處理,因為父類的run方法沒有拋出異常,子類重寫方法也不能拋出異常
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    public MyThread(String name){
        super(name);
    }
}

線程加入
指的是調(diào)用join方法的線程執(zhí)行完了,下面的程序才能執(zhí)行。

public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        MyThread 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 block
            e.printStackTrace();
        }
        my2.start();
        try {
            my2.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        my3.start();
    }

join的用法可以參考:java多線程 join方法以及優(yōu)先級方法,Java多線程中join方法的理解。
(太長不看版= =:join方法就是要等這個自己這個線程走完了,調(diào)用啟動自己這個線程的主線程才能繼續(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 block
            e.printStackTrace();
        }
        for(int i=0;i<10000;i++){
            System.out.println("main");
        }
        my3.start();
    }
}


大概就這個意思

線程禮讓
只能讓線程的執(zhí)行更加和諧,但不能保證絕對謙讓。

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 {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 1000; i++) {
            System.out.println(getName() + ":" + i);
            Thread.yield();
        }
    }

    public MyThread(String name) {
        super(name);
    }
}

守護線程
將該線程標記為守護線程或用戶線程。當正在運行的線程都是守護線程時,Java 虛擬機退出。該方法必須在啟動線程前調(diào)用。該方法首先調(diào)用該線程的 checkAccess 方法,且不帶任何參數(shù)。這可能拋出 SecurityException(在當前線程中)。
拋出:IllegalThreadStateException - 如果該線程處于活動狀態(tài)。
    SecurityException - 如果當前線程無法修改該線程。

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方法我也沒太搞懂= =

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 {
    @Override
    public void run() {
        System.out.println("開始執(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.多線程實現(xiàn)舉例

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

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 {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}
2.那為什么還要有第二種方法呢?

避免了java單繼承帶來的局限性。簡單來說就是我已經(jīng)有一個父類了,那我想實現(xiàn)多線程就不能在繼承另一個父類了。

適合多個相同程序的代碼去處理同一個資源的情況,線程是線程,程序代碼是程序代碼,數(shù)據(jù)有效分離開,降低耦合度。體現(xiàn)面向?qū)ο蟮乃枷搿?/strong>

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

還是在模擬賣票的情景中,三個窗口賣一百張票,這三個窗口要共享這一百張票的資源。如果運用如下程序,則兩個線程各自從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)修飾符
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for(;x>0;x--){
       //標記點1
            System.out.println(getName()+":"+x);
       //標記點2
        }
    }
}

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

2.同步機制

2.1.synchronized

2.1.1.synchronized代碼塊
synchronized修飾的代碼,在一個線程進行的時候,發(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();
    @Override
    public void run() {
        synchronized (obj) {
            for (; x > 0; x--) {
                System.out.println(Thread.currentThread().getName() + ":" + x);
            }
        }
    }
}

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

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;

    @Override
    public 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++;
    }
}

上面這塊代碼也沒出問題,但是我沒明白,明明不是同一個鎖啊,為什么還沒出問題?

2.1.2.synchronized方法
同步方法的默認鎖對象是this。靜態(tài)方法的默認鎖是當前對象的類對象(.class對象)。

@Override
    public synchronized void run() {
        for (; x > 0; x--) {
            System.out.println(Thread.currentThread().getName() + ":" + x);
        }
    }

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

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();

    @Override
    public void run() {
        lock.lock();
        try {//解決出現(xià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 死鎖問題
指兩個或者兩個以上的線程在執(zhí)行過程中因爭奪資源而產(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;
    }
    
    @Override
    public 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.等待喚醒機制
public final void wait(long timeout) throws InterruptedException
在其他線程調(diào)用此對象的 notify() 方法或 notifyAll() 方法,或者超過指定的時間量前,導致當前線程等待。
當前線程必須擁有此對象監(jiān)視器。

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

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

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

public final void notify()

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

通過執(zhí)行此對象的同步實例方法。
通過執(zhí)行在此對象上進行同步的 synchronized 語句的正文。
對于 Class 類型的對象,可以通過執(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;
    }

    @Override
    public 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í)行,還要進行CPU執(zhí)行權(quán)的爭奪。
            }
        }
    }
}

class GetStudent implements Runnable {
    Student s;
    int x;

    GetStudent(Student s) {
        this.s = s;
    }

    @Override
    public void run() {

        for (;;) {
            synchronized (s) {
                if (!s.flag) {
                    try {
                        s.wait();// t2等待了, 立即釋放鎖,醒過來的時候從這里醒來。
                    } 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("這是一個新的組");
        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{
    @Override
    public void run() {
        for(int x=0;x<100;x++){
            System.out.println(Thread.currentThread().getName()+":"+x);
        }
    }
}
七、線程池 1.概述和使用

程序啟動一個新線程成本是比較高的,因為它涉及到要與操作系統(tǒng)進行交互。而使用線程池可以很好的提高性能,尤其是當程序中要創(chuàng)建大量生存期很短的線程時,更應(yīng)該考慮使用線程池。

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

在JDK5之前,我們必須手動實現(xiàn)自己的線程池,從JDK5開始,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{
    @Override
    public void run() {
        for(int x=0;x<100;x++){
            System.out.println(Thread.currentThread()+":"+x);
        }
    }
}
2.線程的實現(xiàn)(第三種方法)

public interface Callable

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

public interface Future

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

public class Demo {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService pool=Executors.newFixedThreadPool(2);
        Future f1=pool.submit(new MyCallable(100));
        Future 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{
    int number;
    public MyCallable(int number) {
        this.number=number;
    }
    @Override
    public Integer call() throws Exception {
        int sum=0;
        for(int x=0;x
八、匿名內(nèi)部類實現(xiàn)多線程
public class Demo {
    public static void main(String[] args){
        new Thread(){
            @Override
            public void run() {
                for(int x=0;x<100;x++){
                    System.out.println(Thread.currentThread().getName()+"---"+x);
                }
            }
        }.start();
        
        new Thread(new Runnable(){
            @Override
            public void run() {
                for(int x=0;x<100;x++){
                    System.out.println(Thread.currentThread().getName()+"---"+x);
                }
            }
        }).start();
        
        new Thread(new Runnable(){
            @Override
            public void run() {
                for(int x=0;x<100;x++){
                    System.out.println("hello---"+x);
                }
            }
        }){
            @Override
            public void run() {
                for(int x=0;x<100;x++){
                    System.out.println("world---"+x);
                }
            }
        }.start();
    }
}
九、定時器 1.概述和使用

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

Timer

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

TimerTask

由 Timer 安排為一次執(zhí)行或重復執(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;
    }
    @Override
    public void run() {
        System.out.println("BANG!");
    }
}

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/67511.html

相關(guān)文章

  • CZ深入淺出Java基礎(chǔ))設(shè)計模式筆記

    摘要:在設(shè)計模式中,所有的設(shè)計模式都遵循這一原則。其實就是說在應(yīng)用程序中,所有的類如果使用或依賴于其他的類,則應(yīng)該依賴這些其他類的抽象類,而不是這些其他類的具體類。使用設(shè)計模式是為了可重用代碼讓代碼更容易被他人理解保證代碼可靠性。 這是劉意老師的JAVA基礎(chǔ)教程的筆記講的賊好,附上傳送門 傳智風清揚-超全面的Java基礎(chǔ) 一、面向?qū)ο笏枷朐O(shè)計原則 1.單一職責原則 其實就是開發(fā)人員經(jīng)常說的高...

    李昌杰 評論0 收藏0
  • CZ深入淺出Java基礎(chǔ))反射

    摘要:分類根類加載器也被稱為引導類加載器,負責核心類的加載比如等。要想解剖一個類必須先要獲取到該類的字節(jié)碼文件對象。 這是劉意老師的JAVA基礎(chǔ)教程的筆記講的賊好,附上傳送門 傳智風清揚-超全面的Java基礎(chǔ) 一、類的加載 1.類初始化的時機 創(chuàng)建類的實例訪問類的靜態(tài)變量,或者為靜態(tài)變量賦值調(diào)用類的靜態(tài)方法使用反射方式來強制創(chuàng)建某個類或接口對應(yīng)的java.lang.Class對象初始化某個類...

    asoren 評論0 收藏0
  • java&javaweb學習筆記(匯總)

    摘要:我的學習筆記匯總標簽筆記分為兩大部分和筆記內(nèi)容主要是對一些基礎(chǔ)特性和編程細節(jié)進行總結(jié)整理,適合了解基礎(chǔ)語法,想進一步深入學習的人如果覺得不錯,請給,這也是對我的鼓勵,有什么意見歡迎留言反饋目錄基礎(chǔ)鞏固筆記反射基礎(chǔ)鞏固筆記泛型基礎(chǔ)鞏 我的java&javaweb學習筆記(匯總) 標簽: java [TOC] 筆記分為兩大部分:javase和javaweb javase javawe...

    yagami 評論0 收藏0
  • 那些年我看過的書 —— 致敬我的大學生活 —— Say Good Bye !

    摘要:開頭正式開啟我入職的里程,現(xiàn)在已是工作了一個星期了,這個星期算是我入職的過渡期,算是知道了學校生活和工作的差距了,總之,盡快習慣這種生活吧。當時是看的廖雪峰的博客自己也用做爬蟲寫過幾篇博客,不過有些是在前人的基礎(chǔ)上寫的。 showImg(https://segmentfault.com/img/remote/1460000010867984); 開頭 2017.08.21 正式開啟我...

    xiaoqibTn 評論0 收藏0
  • 深入理解java虛擬機》學習筆記系列——java內(nèi)存區(qū)域劃分

    摘要:運行時數(shù)據(jù)區(qū)域的學習,是學習以及機制的基礎(chǔ),也是深入理解對象創(chuàng)建及運行過程的前提。了解內(nèi)存區(qū)域劃分,是學習概念的前提。 Java 運行時數(shù)據(jù)區(qū)域的學習,是學習 jvm 以及 GC 機制的基礎(chǔ),也是深入理解 java 對象創(chuàng)建及運行過程的前提。廢話不多說,直接進入正題: 一張圖總結(jié) showImg(https://segmentfault.com/img/bVOMAn?w=685&h=5...

    史占廣 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<