一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java中后臺線程實例解析

Java中后臺線程實例解析

2021-03-31 13:23szu_lg Java教程

這篇文章主要介紹了Java中后臺線程實例解析,分享了相關代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下

本文研究的主要是Java后臺線程的相關問題,具體介紹如下。

以前從來沒有聽說過,java中有后臺線程這種東西。一般來說,JVM(JAVA虛擬機)中一般會包括倆種線程,分別是用戶線程和后臺線程。所謂后臺線程(daemon)線程指的是:在程序運行的時候在后臺提供的一種通用的服務的線程,并且這種線程并不屬于程序中不可或缺的部分。因此,當所有的非后臺線程結束的時候,也就是用戶線程都結束的時候,程序也就終止了。同時,會殺死進程中的所有的后臺線程。反過來說,只要有任何非后臺線程還在運行,程序就不會結束。不如執行main()的就是一個非后臺線程。

基于這個特點,當虛擬機中的用戶線程全部退出運行時,守護線程沒有服務的對象后,JVM也就退出了。

這點JDK源碼中的介紹已經說明這一點了。

* Marks this thread as either a {@linkplain #isDaemon daemon} thread
* or a user thread. The Java Virtual Machine exits when the only
* threads running are all daemon threads.

1.后臺線程的啟動的條件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*必須在啟動線程之前調用SetDaemon()方法,才能把這個線程設置為后臺線程。
* 在這個程序里面,當我們輸入了字符串以后,那么Main線程就會停止運行了
* 那么程序中已經沒有可以運行的用戶的線程了。所以后臺線程就會被停止了
* JVM也就會被停停止了,感興趣的讀者可以自己嘗試一下*/
public class DaemonRunner implements Runnable {
    @Override
     public void run() {
        while (true) {
            for (int i = 0; i < 3; i++) {
                System.out.println("守護線程" + i);
            }
        }
    }
    public static void main(String[] args) {
        Thread daemon = new Thread(new DaemonRunner());
        daemon.setDaemon(true);
        daemon.start();
        Scanner s = new Scanner(System.in);
        String string=s.nextLine();
        Runtime.getRuntime().addShutdownHook(new Thread(){
            @Override
               public void run() {
                super.run();
                System.out.println("JVM退出");
                try {
                    TimeUnit.MILLISECONDS.sleep(50);
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        );
    }
}

2.在后臺線程中啟動的線程都屬于后臺線程。盡管你沒有明確指明它們是后臺線程,但是它們的確是后臺線程。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*可以通過調用isDaemon()方法來確定線程是否是一個后臺線程。如果是一個后臺線程,
* 那么它創建的任何線程都被自動設置成后臺的線程
* 在這個實例中,Daemon線程被設置成了后臺模式,然后派生出許多子線程,這些線程并沒有被設置成
* 后臺模式,不過它們的確是后臺線程。接著,Daemon線程進入了無限循環,并且在循環里調用了yield方法
* 把控制權交給其它的線程或者進程*/
class Daemon implements Runnable{
    private Thread[] t = new Thread[10];
    @Override
     public void run() {
        for (int i = 0; i < t.length; i++) {
            t[i] = new Thread(new DaemonSpawn());
            t[i].start();
            System.out.println("DaemonSpawn " + i + "started");
        }
        for (int i = 0; i < t.length; i++) {
            System.out.println("t[" + i + "].isDaemon" + t[i].isDaemon());
        }
        while (true) {
            Thread.yield();
        }
    }
}
class DaemonSpawn implements Runnable{
    @Override
     public void run() {
        while (true) {
            Thread.yield();
        }
    }
}
public class Daemons {
    public static void main(String[] args) {
        Thread d = new Thread(new Daemon());
        d.setDaemon(true);
        d.start();
        System.out.println("d.isDaemon()=" + d.isDaemon());
        try {
            TimeUnit.SECONDS.sleep(1);
            //讓啟動的后臺的線程可以獲得一定的執行的時間。
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

最后的執行的結果如下:

d.isDaemon()=true
DaemonSpawn 0started
DaemonSpawn 1started
DaemonSpawn 2started
DaemonSpawn 3started
DaemonSpawn 4started
DaemonSpawn 5started
DaemonSpawn 6started
DaemonSpawn 7started
DaemonSpawn 8started
DaemonSpawn 9started
t[0].isDaemontrue
t[1].isDaemontrue
t[2].isDaemontrue
t[3].isDaemontrue
t[4].isDaemontrue
t[5].isDaemontrue
t[6].isDaemontrue
t[7].isDaemontrue
t[8].isDaemontrue
t[9].isDaemontrue

3.通過為Executors.newCachedThreadPool()方法指定一個ThreadFactory的對象。通過這種方法,我們也可以將
我們想要啟動的線程設置為后臺線程。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*在這個例子中,對于這個靜態的構造方法:Executors.newCachedThreadPool(new DaemonThreadFactory()
* 我們可以為傳入一個ThreadFactory的對象,那么我們就可以通過這種方法,將我們想要啟動的線程設置為后臺線程
* 這是要注意的。*/
class DaemonThreadFactory implements ThreadFactory{
    @Override
      public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }
}
/*在這個例子中,在Main方法中,會首先調用Main方法中的普通的方法,“ System.out.println("All dameons started");”
* 所以會首先打印這一條語句。然后在主線程休眠期間,相應的后臺線程,就會獲得執行的時間,最后在Main線程
* 結束了運行的時候,也就是當Main線程從休眠中恢復過來的時候,那么Main線性就會結束運行。接著,
* 那么所有的后臺的線程都會停止。JVM也會停止執行。*/
public class DaemonFromFactory implements Runnable {
    @Override
      public void run() {
        try {
            while (true) {
                TimeUnit.MILLISECONDS.sleep(100);
                System.out.println(Thread.currentThread() + " " + this);
            }
        }
        catch (InterruptedException e) {
            System.out.println("Interrupted");
        }
    }
    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool(new DaemonThreadFactory());
        for (int i = 0; i < 10; i++) {
            exec.execute(new DaemonFromFactory());
        }
        System.out.println("All dameons started");
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

最后的輸出的結果為:

All dameons started
Thread[Thread-3,5,main] Concurrency.DaemonFromFactory@56214c1
Thread[Thread-2,5,main] Concurrency.DaemonFromFactory@5724147d
Thread[Thread-0,5,main] Concurrency.DaemonFromFactory@144fe080
Thread[Thread-1,5,main] Concurrency.DaemonFromFactory@104fa29e
Thread[Thread-8,5,main] Concurrency.DaemonFromFactory@5b069a7f
Thread[Thread-9,5,main] Concurrency.DaemonFromFactory@1a7288d1
Thread[Thread-7,5,main] Concurrency.DaemonFromFactory@25144c3e
Thread[Thread-4,5,main] Concurrency.DaemonFromFactory@288523d
Thread[Thread-6,5,main] Concurrency.DaemonFromFactory@1edae2a8
Thread[Thread-5,5,main] Concurrency.DaemonFromFactory@626007aa
Thread[Thread-3,5,main] Concurrency.DaemonFromFactory@56214c1
Thread[Thread-2,5,main] Concurrency.DaemonFromFactory@5724147d
Thread[Thread-6,5,main] Concurrency.DaemonFromFactory@1edae2a8
Thread[Thread-5,5,main] Concurrency.DaemonFromFactory@626007aa
Thread[Thread-4,5,main] Concurrency.DaemonFromFactory@288523d
Thread[Thread-9,5,main] Concurrency.DaemonFromFactory@1a7288d1
Thread[Thread-7,5,main] Concurrency.DaemonFromFactory@25144c3e
Thread[Thread-8,5,main] Concurrency.DaemonFromFactory@5b069a7f
Thread[Thread-1,5,main] Concurrency.DaemonFromFactory@104fa29e
Thread[Thread-0,5,main] Concurrency.DaemonFromFactory@144fe080
Thread[Thread-2,5,main] Concurrency.DaemonFromFactory@5724147d
Thread[Thread-3,5,main] Concurrency.DaemonFromFactory@56214c1
Thread[Thread-6,5,main] Concurrency.DaemonFromFactory@1edae2a8
Thread[Thread-1,5,main] Concurrency.DaemonFromFactory@104fa29e
Thread[Thread-0,5,main] Concurrency.DaemonFromFactory@144fe080
Thread[Thread-7,5,main] Concurrency.DaemonFromFactory@25144c3e
Thread[Thread-8,5,main] Concurrency.DaemonFromFactory@5b069a7f
Thread[Thread-5,5,main] Concurrency.DaemonFromFactory@626007aa
Thread[Thread-9,5,main] Concurrency.DaemonFromFactory@1a7288d1
Thread[Thread-4,5,main] Concurrency.DaemonFromFactory@288523d
Thread[Thread-2,5,main] Concurrency.DaemonFromFactory@5724147d
Thread[Thread-3,5,main] Concurrency.DaemonFromFactory@56214c1
Thread[Thread-8,5,main] Concurrency.DaemonFromFactory@5b069a7f
Thread[Thread-7,5,main] Concurrency.DaemonFromFactory@25144c3e
Thread[Thread-4,5,main] Concurrency.DaemonFromFactory@288523d
Thread[Thread-6,5,main] Concurrency.DaemonFromFactory@1edae2a8
Thread[Thread-1,5,main] Concurrency.DaemonFromFactory@104fa29e
Thread[Thread-0,5,main] Concurrency.DaemonFromFactory@144fe080
Thread[Thread-9,5,main] Concurrency.DaemonFromFactory@1a7288d1
Thread[Thread-5,5,main] Concurrency.DaemonFromFactory@626007aa
Thread[Thread-3,5,main] Concurrency.DaemonFromFactory@56214c1
Thread[Thread-2,5,main] Concurrency.DaemonFromFactory@5724147d
Thread[Thread-8,5,main] Concurrency.DaemonFromFactory@5b069a7f

4.首先應該意識到如果在用戶線程突然退出的時候,那么后臺線程在不執行finally子句的情況下就會終止其run方法。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*當你調用這個程序的時候,你將看到finally子句不會執行,但是如果你注釋掉對setDaemon()的調用,你將看到
* finally 子句將會執行.
* 這種行為是正確的。即便你基于前面對finally給出的承諾,并不希望出現這種行為。但是情況就是這樣
* 當最后一個非后臺的線程終止的時候,后臺線程就會突然的停止。因為一旦main()退出后,JVM就會立即關閉所有后臺的
* 線程。因為你不能以優雅的方式來關閉后臺線程,所以它們幾乎不是一種好的思想。非后臺的Executor通常是一種
* 更好的方式,因為Executor控制的所有的任務可以同時被關閉。*/
class ADaemon implements Runnable{
  @Override
  public void run() {
    System.out.println("Starting ADaemon");
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      System.out.println("Exiting via InterruptedException");
    }finally {
      System.out.println("This should always run?");
    }
  }
}
public class DaemonsDontRunFinally {
  public static void main(String[] args) {
    Thread t = new Thread(new ADaemon());
    t.setDaemon(true);
    t.start();
  }
}

最后的輸出的結果如下:

Starting ADaemon

但是如果情況變為如下的情況,輸出的結果又會不一樣了:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class ADaemon implements Runnable{
  @Override
  public void run() {
    System.out.println("Starting ADaemon");
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      System.out.println("Exiting via InterruptedException");
    }finally {
      System.out.println("This should always run?");
    }
  }
}
public class DaemonsDontRunFinally {
  public static void main(String[] args) {
    Thread t = new Thread(new ADaemon());
    t.setDaemon(true);
    t.start();
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

由于主線程不是突然退出的,主線程在休眠期間,后臺線程得到了執行的時間,所以最后的打印的結果為:

Starting ADaemon
This should always run?

總結

以上就是本文關于Java中后臺線程實例解析的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

原文鏈接:http://blog.csdn.net/li12412414/article/details/51418182

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 十六以下岁女子毛片免费 | 四虎网址| 嗯啊好爽视频 | 日韩一品在线播放视频一品免费 | 国产精品亚洲片夜色在线 | 美女天天操| 免费在线视频一区 | 国产精品亚洲综合久久 | 明星裸乳照无奶罩 | 姐姐不~不可以动漫在线观看 | 91精品久久一区二区三区 | 国产成人看片免费视频观看 | 欧美日韩高清一区 | 久久99热狠狠色AV蜜臀 | 国产精品福利久久2020 | 国产综合久久久久久 | 小鸟酱视频在线观看 | 国产成人精品免费视频大全五级 | 亚洲精品国产综合久久一线 | 日韩欧免费一区二区三区 | 日本高清在线看免费观看 | 双子母性本能在线 | 911色_911色sss在线观看 | 成年看片免费高清观看 | 日韩一品在线播放视频一品免费 | 精品久久久久久亚洲精品 | 免费一级生活片 | 99精品国产自在现线观看 | 俄罗斯一级成人毛片 | 久久综久久美利坚合众国 | 国产在线98福利播放视频免费 | 嫩模被黑人粗大挺进 | 2021国产麻豆剧传媒新片 | 99久久精品国产免费 | 亚洲日本免费 | 日本又黄又裸一级大黄裸片 | 岛国虐乳紧缚媚药调教 | 国产高清免费午夜在线视频 | 色播开心网 | 国产剧情一区二区三区 | 国产全部理论片线观看 |