java線程一之建立線程、線程池以及多線程運行時間統計

線程和進程的基本概念

進程和線程是動態的概念。 html

        進程是 「執行中的程序「,是一個動詞,而程序是一個名詞,進程運行中程序的」代碼「,並且還有本身的計數器,寄存器,它會向系統申請系統資源。 java

        線程是進程中的一個控制流。一個程序可能可能包含多個任務併發運行,而線程就是指一個任務重頭到尾的執行流。 多線程

        說的在簡單點,線程是執行中的任務,一個程序包含多個任務。 併發

 

多線程

       單處理器中,爲提升處理器的使用率(最終目標),使得程序在進行IO輸入出等不須要處理器時,也可以讓處理器在運轉,引進多線程處理機制。多線程可使得程序運行的更快,執行效率更高,交互性更強,這是不言而喻的! ide

 

建立任務和線程

        一個任務是一個對象,因此爲建立一個任務,必須定義一個類,定義一個任務類,爲了說明這是一個任務類,它須要實現Runnable接口,這個接口只包含一個run方法。 學習

當咱們定義好任務類taskClass以後,就能夠用它的構造方法建立一個任務啦:TaskClass  task = new TaskClass(.....); this

        咱們建立的任務只能在線程中運行,Thread類中包含了建立線程以及控制線程的衆多方法。使用下面的語句建立任務線程:Thread  thread  = new Thread(task); 線程

        而後調用start()方法告訴java虛擬機該線程準備運行thread.start();以後java虛擬機經過調用任務的run()方法執行任務。 設計

 

事例代碼:htm

public class TaskThreadDemo{
	public static void main(String[] args)
	{
		//建立任務   而且須要爲任務 建立 任務類,使用該類的構造方法建立任務
		PrintChar printA = new PrintChar('a',100);
		PrintChar printB = new PrintChar('b',100);
		PrintNum print100 = new PrintNum(100);
		
		//爲任務建立線程
		Thread thread1 = new Thread(printA);
		Thread thread2 = new Thread(printB);
		Thread thread3= new Thread(print100);
		
		//告訴虛擬機器線程開始運行
		thread1.start();
		thread2.start();
		thread3.start();
	}
}

class PrintChar implements Runnable
{
	private char  charToPrint;
	private int items;
	
	public PrintChar(char c,int t)
	{
		charToPrint = c;
		items = t;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<items;i++)
		{
			System.out.print(charToPrint);
		}
	}
}

class PrintNum implements Runnable
{
	private int lastNumb;
	public PrintNum(int n)
	{
		lastNumb = n;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i= 1;i<100;i++)
		{
			System.out.print(" "+lastNumb); 
		}
	}

}

 

6fdaf34c50434bf5bab9d149c7fccc4c

 

一個好玩的閃爍文本框,直接用線程,不用main方法

import javax.swing.JApplet;
import javax.swing.JLabel;
public class FlashingText extends JApplet implements Runnable {
	private static final long serialVersionUID = 1L;
	private JLabel jlbText = new JLabel("Welcome",JLabel.CENTER);
	
	public FlashingText()
	{
		add(jlbText);
		new Thread(this).start();
	}
	
	public void run()
	{
		try {
			while(true)
			{
				if(jlbText.getText()==null)
					jlbText.setText("Welcome");
				else 
					jlbText.setText(null);
				Thread.sleep(200);
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}

 

ed611650e460458198ca7b12d26f387fa28aa6938f9645578293e2a7e193c531

 

Thread類

        Thread類實現了Runnable接口,它包含爲任務而建立線程的構造方法,以及控制方法,下圖就是Thread類常見的控制線程的方法:

iirj8`ilw}dr

          由於Thread類實現了Runnable接口,因此能夠定義一個Thread的擴展類,裏面實現run方法,這樣也能夠建立一個線程類,但並非很推薦這種方法,由於它將建立任務和運行任務的機制混在了一塊兒,將任務從線程中分離出來比較好,即儘可能使用Runnable接口建立線程,這樣獲得的線程更加靈活,避免了java單繼承帶來的侷限性

 

線程池

           線程池是管理併發執行任個數的理想方法,java提供Executor接口來執行線程池中的任務,提供ExecutorService接口來管理和控制任務。爲了建立Executor接口實例,咱們能夠用Executors類,Executors類提供了建立Executor接口對象的靜態方法,下圖描述了上面的上面所說的關係。

clipboard

 

       線程池中的shutdown()方法通常都是放在main方法的後面部分,當因此的線程都添加到線程池中,即使有線程沒有執行完畢,也可能會關閉線程池,未執行完的線程繼續執行,因此main方法可能比子線程先結束。

利用isTerminated()進行線程池中全部線程運行時間的統計

       假若但願主線程在子線程所有作完以後在執行,能夠考慮讓因此的子線程用jion方法,但這可能致使全部子線程變成串行,不是很好的辦法,固然咱們也能夠多線程的輔助類CountDownLatch,這是一個與計時器有點相似功能的類。此次在看書學習的時候,發現了一個更好的辦法,就是在shutdown()方法後加上一句while(!executor.isTerminated()){},這是一個不錯的方法(不過我把shoudown()方法放在該while語句後面,就會陷入死循環,應該是要先關閉線程池,在判斷線程池中的線程是否所有終止,由於也有可能在while語句後面在添加新的子線程)。

       isTerminated()方法:若是線程池中因此線程都已完成並終止,則返回true.

       可使用CountDownLatch 和上面的方法對程序運行計時統計,不過我記得CountDownLatch類是須要指定線程的個數。

事例代碼

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorDemo {
	public static void main(String[] args){
		long start = System.currentTimeMillis();
		System.out.println("當前時間"+"  "+start);
		ExecutorService executor = Executors.newFixedThreadPool(4);
		
		executor.execute(new PrintChar('a',100));
		executor.execute(new PrintChar('b',100));
		executor.execute(new PrintChar('c',100));
	    executor.execute(new PrintNum(100));
	    
	    executor.shutdown();
		while(!executor.isTerminated()){
			//System.out.print("-");
		};
		
		long end = System.currentTimeMillis();
		System.out.println("\n當前時間"+"  "+end);
		System.out.println("\n用時"+"  "+(end-start)+"毫秒");
	}
}
 
運行截圖
3015774f9c88408286aa07f7c77a10db 截圖1      572ff3bc5ea7495d9f207f5971a731a9截圖2

         不過不知道運行太快的緣由,仍是啥別的緣由, 會出現截圖2的狀況,網上不多關於isTerminated()方法的介紹,若有大神知道緣由,還請告知小弟。

 

         這篇博客是本身在學習《java語言程序設計進階篇》時所在筆記,代碼出自書上,最後那個記時的加了計時部分。大三開學在即,但願如今來學java還來得及。

本文出自於博客園蘭幽,轉載請說明出處。

相關文章
相關標籤/搜索