1. 程式人生 > >執行緒的幾種建立方式並實現賣票功能

執行緒的幾種建立方式並實現賣票功能

本篇簡單的講下執行緒的幾種建立方式並相應的實現售票功能

一、執行緒建立

public class ThreadTest {

	public static void main(String[] args) throws InterruptedException, ExecutionException {
		
		//執行緒的三種建立方式
		//1繼承thread類  重寫run方法
		createThread thread=new createThread();
		thread.start();
		//2實現Runnable介面 重寫run方法
		createThread1 thread1=new createThread1();
		Thread thread2=new Thread(thread1);
		thread2.start();
		//3實現callable介面,重寫call方法
		createThread2 thred2=new createThread2();
		FutureTask<String> ft=new FutureTask<String>(thred2);
                new Thread(ft).start();
		System.out.println("返回值:"+ft.get());
		
		//4利用ExecutorService執行緒池來管理執行緒
		ExecutorService threadPool=Executors.newFixedThreadPool(2);
		threadPool.execute(thread1);
	}	
}
//繼承thread類
class createThread extends Thread{
	@Override
	public void run() {
		for(int i=0;i<10;i++){
			System.out.println(Thread.currentThread().getName()+" i:"+i);
		}
	}
}
//實現runnable介面
class createThread1 implements Runnable{

	@Override
	public void run() {
		for(int i=0;i<10;i++){
			System.out.println(Thread.currentThread().getName()+" i:"+i);
		}
	}
	
}
//實現callable介面
class createThread2 implements Callable<String>{

	@Override
	public String call() throws Exception {
		for(int i=0;i<10;i++){
			System.out.println(Thread.currentThread().getName()+" i:"+i);
		}
		return "該方法建立執行緒有返回值";
	}
	
}

第三種方式是利用了FutureTask類和Callable介面

首先建立Callable介面的實現類,實現call()方法,該方法比run()方法要強大,會有返回值返回。

使用FutureTask類包裝Callable物件,建立thread物件,將FutureTask物件傳給thrad,呼叫start()方法開啟執行緒。呼叫FutureTask物件的get()方法可以獲得執行緒結束後的返回值。

其他三者之間的比較,無非是繼承thread類的,獲取當前執行緒可以直接this.getName(),不能再繼承其他的類了。

而實現介面的方式獲取當前執行緒必須用Thread.currentThread().getName(),還能夠再繼承其他的類。

二、基於上面的三種方式實現賣票功能

描述:有四個視窗在買票,總票數為100,每售出一張,打印出視窗號和票的序號。每個視窗命名"視窗1”到"視窗4"

(1)繼承thread實現

public static void main(String[] args) {
		ticketsWindow tic1=new ticketsWindow();
		tic1.setName("視窗1");
		ticketsWindow tic2=new ticketsWindow();
		tic2.setName("視窗2");
		ticketsWindow tic3=new ticketsWindow();
		tic3.setName("視窗3");
		ticketsWindow tic4=new ticketsWindow();
		tic4.setName("視窗4");
		tic1.start();
		tic2.start();
		tic3.start();
		tic4.start();


	}
	
}

class ticketsWindow extends Thread{
	private static int ticket=100;
	private static Object o=new Object();
	public void run(){
		while(true){
			synchronized (o) {
				if(ticket>0){
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					ticket--;
					System.out.println(getName()+":第"+(100-ticket)+"張票已被售出");
				}else{
					break;
				}
			}
		}
	}
}

(2)實現Runnable介面

public static void main(String[] args) {
		ticketsWindows tkw = new ticketsWindows();
		Thread s1 = new Thread(tkw, "視窗1");
		Thread s2 = new Thread(tkw, "視窗2");
		Thread s3 = new Thread(tkw, "視窗3");
		Thread s4 = new Thread(tkw, "視窗4");
		s1.start();
		s2.start();
		s3.start();
		s4.start();
	}

}

class ticketsWindows implements Runnable {
	private static int ticket = 100;

	@Override
	public void run() {
		while (true) {
			synchronized (this) {
				if (ticket > 0) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					--ticket;
					System.out.println(Thread.currentThread().getName() + " :第"
							+ (100 - ticket) + "張票已售出");
				} else {
					break;
				}
			}
		}
	}

(3)利用ExecutorService執行緒池

public class TicketThread3 {

	public static void main(String[] args) {
		ExecutorService threadPool = Executors.newFixedThreadPool(4);
		Ticket tickT = new Ticket();
		for (int i = 1; i < 5; i++) {
			Thread thread = new Thread(tickT);
			threadPool.execute(thread);
		}

	}
}

class Ticket implements Runnable {

	private static int i = 10;

	@Override
	public void run() {
		while (true) {
			synchronized (this) {
				if (i > 0) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					--i;
					System.out.println(Thread.currentThread().getName() + " :第"
							+ (10 - i) + "張票已售出");
				} else {
					break;
				}
			}
		}

	}

}

輸出結果: