国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Java語言導學筆記Chapter8Thread

2019-11-14 15:03:37
字體:
來源:轉載
供稿:網友

8.1 什么是線程

def: 線程是程序內的一個單一的順序控制流程

作為一個順序的控制流程,線程必須在運行它的程序中占用一些資源。例如,線程必須有它自己的執行堆棧和程序計數器。在線程內運行的代碼只在此上下文中工作。其他一些文章將線程稱為執行上下文(execution context)。

如果你的程序必須反復執行一個任務,那么應該考慮使用java.util.Timer類。對于在一段程序后執行另一個任務,Timer類也很有用。

如果你正在編寫一個具有圖形的用戶界面(GUI)的程序,那么應該使用javax.swing.Timer類。

對線程的基本支持由java.lang.Thread類提供。它提供了一個線程API并提供了線程的所有共有行為。這些行為包括啟動、睡眠、運行、放棄和給予優先級。要使用Thread類實現線程,需要為它提供一個run方法,run方法實際執行線程的任務。

 

8.2 使用Timer和TimerTask類

Reminder.java這個例子使用計時器在一段延遲時間之后執行一個任務。

import java.util.Timer;

import java.util.TimerTask;

 

public class Reminder{

         Timer timer;

        

         public Reminder(int seconds){

                   timer = new Timer();

                   timer.schedule(new RemindTask(), seconds*1000);

         }

        

         class RemindTask extends TimerTask{

                   public void run(){

                            System.out.

                            timer.cancel(); //Terminate the timer thread

                   }

         }

        

         public static void main(String args[]){

                   new Reminder(5);

                   System.out.println("Task scheduled.");

         }

}

實現和調度有計時器線程執行的任務的基本部分。

1、  實現一個定制的TimerTask子類。run方法包含執行任務的代碼。

2、  通過實例化Timer類創建一個線程。

3、  實例化一個計時器任務對象(new RenmindTask())。

4、  調度這個計時器任務的執行。本例使用schedule方法。

讓一個任務在特定時間執行:

import java.util.Timer;

import java.util.TimerTask;

import java.util.Calendar;

import java.util.Date;

 

public class Reminder{

         Timer timer;

        

         public Reminder(int seconds){

                   timer = new Timer();

                   timer.schedule(new ReminderTask(), seconds*1000);

         }

        

         public Reminder(){

                   Calendar calendar = Calendar.getInstance();

                   calendar.set(Calendar.HOUR_OF_DAY, 11);

                   calendar.set(Calendar.MINUTE, 9);

                   calendar.set(Calendar.SECOND, 0);

                   Date time = calendar.getTime();

        

                   timer = new Timer();

                   timer.schedule(new RemindTask2(), time);

         }

        

         class ReminderTask extends TimerTask{

                   public void run(){

                            System.out.println("Time's up!");

                            timer.cancel(); //Terminate the timer thread

                   }

         }

        

         class RemindTask2 extends TimerTask{

                   public void run(){

                            System.out.println("Time's up! Ring on.");

                            timer.cancel(); //Terminate the timer thread

                   }

         }

        

         public static void main(String args[]){

                   new Reminder(5);

                   new Reminder();

                   System.out.println("Task scheduled.");

         }

}

在默認情況下,只要程序的計時器線程在運行,程序就一直運行。有四種方式可以終止計時器線程。

1、  在計時器線程上調用cancel方法。

2、  使計時器成為“守護線程”(deamon),辦法是這樣創建計時器: new Timer(true) 。如果程序中僅剩下守護線程,那么程序退出。

3、  在計時器的被調度的所有任務都完成后,刪除所有對Timer對象的引用。最后計時器的線程將退出。

4、  調用System.exit方法,使整個程序退出。

重復執行任務:

import java.util.Timer;

import java.util.TimerTask;

import java.awt.Toolkit;

 

/**

 * Schedule a task that executes once every second.

 */

 

public class AnnoyingBeep {

 

    Toolkit toolkit;

    Timer timer;

 

    public AnnoyingBeep() {

                   toolkit = Toolkit.getDefaultToolkit();

        timer = new Timer();

        timer.schedule(new RemindTask(),

                                                  0,        //initial delay

                                                  1*1000);  //subsequent rate

    }

 

    class RemindTask extends TimerTask {

                   int numWarningBeeps = 3;

        public void run(){

                            if (numWarningBeeps > 0) {

                                     toolkit.beep();

                                     System.out.println("Beep!");

                                     numWarningBeeps--;               

                            } else {                                 

                                     toolkit.beep();

                                     System.out.println("Time's up!");

                                     //timer.cancel(); //Not necessary because we call System.exit

                                     System.exit(0);   //Stops the AWT thread (and everything else)                   

                            }

                   }

         }

 

    public static void main(String args[]) {

                   System.out.println("About to schedule task.");

                   new AnnoyingBeep();

                   System.out.println("Task scheduled.");                    

         }

}

AnnoyingBeep程序使用schedule方法的三參數版本,指定它的任務應該馬上開始執行,并且每1秒執行一次。下面是所有可用來調度任務反復執行的方法:

schedule(TimerTask task, long delay, long period)

schedule(TimerTask task, Date time, long period)

scheduleAtFixedRate(TimerTask task, long delay, long period)

scheduleAtFixedRate(TimerTask task, Date firstTime, long period)

在調度任務反復執行時,如果執行的平滑性很重要,那么應該使用schedule方法之一,如果一次蜂鳴聲因為某種原因推遲了,那么后續的所有的蜂鳴聲將相應延遲;如果時間的同步更重要,那么應該使用scheduleAtFixedRate方法之一,如果想讓程序在第一次蜂鳴后正好3秒退出,,如果一次蜂鳴聲因為某種原因延遲了,那么兩次蜂鳴的時間可能較近,小于1秒。

 

8.3 定制線程的run方法

有兩種技術可以為線程提供run方法:

1、  對Thread類進行子類化并覆蓋run方法

2、  實現Runnable接口

對Thread類進行子類化并覆蓋run方法

Thread類本身是一個Runnable對象。

public class SimpleThread extends Thread{

         public SimpleThread(String str){

                   super(str);

         }

        

         public void run(){

                   for(int i = 0; i < 10; i++){

                            System.out.println(i + " " + getName());

                            try{

                                     sleep((int)(Math.random()*1000));

                            }catch(InterruptedException e){}

                   }

                   System.out.println("Done! " + getName());

         }

}

第一個方法是構造器,調用超類構造器設置線程名稱。

public class TwoThreadDemo{

         public static void main(String[] args){

                   new SimpleThread("Jamaica").start();

                   new SimpleThread("Fiji").start();

         }

}

 

實現Runnable接口

import java.awt.Graphics;

import java.util.*;

import java.text.DateFormat;

import java.applet.Applet;

 

public class Clock extends Applet implements Runnable {

         private Thread clockThread = null;

         public void start(){

                   if(clockThread == null){

                            clockThread = new Thread(this, "Clock");

                            clockThread.start();

                   }

         }

         public void run(){

                   Thread myThread = Thread.currentThread();

                   while(clockThread == myThread){

                            repaint();

                            try{

                                     Thread.sleep(1000);

                            }catch(InterruptedException e){

                                     //the VM doesn't want us to sleep anymore;

                                     //so get back to work

                            }

                   }

         }

         public void paint(Graphics g){

                   //get the time and convert it to a date

                   Calendar cal = Calendar.getInstance();

                   Date date = cal.getTime();

                   //format it and display it

                   DateFormat dateFormatter = DateFormat.getTimeInstance();

                   g.drawString(dateFormatter.format(date), 5, 10);

         }

         //overrides Applet's stop method, not Thread's

         public void stop(){

                   clockThread = null;

         }

}

 

<html>

         <head>

                   <title>Clock</title>

         </head>

         <body>

                   I'm now listening to OuRuoLa

                   <APPLET CODE= "Clock.class" WIDTH=150 HEIGHT=35></APPLET>

         </body>

</html>

 

這個Clock applet 顯示當前時間并且每1秒更新一次。問題是會間接的閃爍,或許和CPU的工作狀態有關。用appletviewer Clock.html查看。

Clock applet的run方法進行循環,知道瀏覽器要求他停止。在循環的每次迭代期間,時鐘重新繪制它的顯示。

如果你的淚必須子類化另一個類,那么應該使用Runnable接口。

8.4 線程的生存周期

1、創建線程

         clockThread = new Thread(this, "Clock"); 執行后Clock applet處于”新線程”狀態。此時線程僅僅是一個空的Thread對象,這時只能啟動線程,調用除start方法外的任何方法都是無意義的,而且會導致IllegalThreadStateException。實際上,只要在線程上調用一個方法,而此線程的狀態不允許此方法調用,那么運行時系統都會拋出IllegalThreadStateException。

2、啟動線程

clockThread.start(); start方法分配線程所需的系統資源,調度線程運行,并調用線程的run方法。

start方法返回后,線程處于“正在運行”狀態。實際情況要更復雜。如果計算機只有一個處理器,這樣就不可能同時運行所有”正在運行“的線程。Java運行時環境必須實現一個調度方案,以便在所有”正在運行“的線程分享處理器。所以在任何給定時刻,”正在運行”的線程可能正在等待輪到它使用CPU。

public void run(){

                   Thread myThread = Thread.currentThread();

                   while(clockThread == myThread){

                            repaint();

                            try{

                                     Thread.sleep(1000);

                            }catch(InterruptedException e){

                                     //the VM doesn't want us to sleep anymore;

                                     //so get back to work

                            }

                   }

         }

Clock的run方法在條件clockThread == myThread成立時一直循環。它使線程和applet平緩地退出。在循環中,applet重新繪制本身,然后讓線程睡眠1000毫秒。

1、  使線程不可運行

當以下事件之一發生時,線程變成“不可運行”狀態:

它的sleep方法被調用;

線程調用wait方法等待某個條件得到滿足;

線程因I/O而阻塞。

對于每個進入“不可運行“狀態的入口,有一個特定的不同出口將線程返回到”可運行“狀態。

如果一個線程已經進入睡眠狀態,那么必須經過指定的睡眠時間(毫秒數);

如果一個線程正在等待某個條件,那么另一個對象必須通過調用notify或notifyAll告知正在等待的線程條件發生了改變;

如果一個線程因I/O而阻塞,那么I/O必須完成。

2、  停止線程

自然消亡;

while(clockThread == myThread)這個條件表示,當前執行的線程不等于clockThread時循環退出。當你離開頁面時,運行此applet的應用程序調用applet的stop方法。然后,這個方法設置clockThread為null,由此讓主循環終止run方法。如果重新訪問這個頁面,那么再次調用start方法,時鐘在一個新線程中再次啟動。即使停止和啟動applet的時間快于循環一次的迭代,clockThread線程也將不同于myThread,循環將終止。

3、  isAlive方法

返回false,線程處于”新線程“狀態,或者已經消亡。返回true,線程處于”可運行“或者”不可運行“。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 广德县| 门源| 调兵山市| 白山市| 潍坊市| 云阳县| 临海市| 苍溪县| 东乌| 富蕴县| 沙田区| 西畴县| 扶余县| 剑川县| 南康市| 宽甸| 宁阳县| 泾源县| 鄂托克前旗| 凯里市| 邵阳市| 珲春市| 平舆县| 自贡市| 攀枝花市| 洱源县| 炉霍县| 黄梅县| 防城港市| 永寿县| 台中县| 桂东县| 克东县| 佛坪县| 南昌市| 仁化县| 历史| 盈江县| 阿图什市| 汉寿县| 汤原县|