1. 程式人生 > >Java多執行緒學習之實現方式

Java多執行緒學習之實現方式

一、實現多執行緒的方式

1.繼承Thread類

步驟:

A:自定義MyThread類繼承Thread類;

B:重寫run()方法,包含被執行緒執行的程式碼;

C:建立物件;

D:啟動執行緒

package thread;

public class ThreadPriority extends Thread{
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i = 0; i < 100; i++){
			System.out.println(getName()+"--"+i);
		}
	}
}
package thread;

public class ThreadPriorityDemo {
	public static void main(String[] args) {
		ThreadPriority tp1 = new ThreadPriority();
		ThreadPriority tp2 = new ThreadPriority();
		ThreadPriority tp3 = new ThreadPriority();
		
		//設定執行緒優先順序,最大值為10,最小為1,預設為5
		tp1.setPriority(10);
		tp2.setPriority(1);
		
		//start()方法啟用執行緒
		tp1.start();
		tp2.start();
		tp3.start();
	}
}

2.實現Runnable介面

步驟:

A:自定義類MyRunnable實現Runnable介面;

B:重寫run()方法;

C:建立MyRunnable類的物件;

D:建立Thread類物件,把上一步建立的類物件當作構造引數

package thread;

public 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);
		}
	}
}
package thread;

public class MyRunnableDemo {
	public static void main(String[] args) {
		MyRunnable my = new MyRunnable();  
		
		Thread t1 = new Thread(my);
		Thread t2 = new Thread(my);
		
		t1.start();
		t2.start();
	}
}

 

二、多執行緒模擬出售電影票

1.使用同步解決執行緒安全問題

package thread;

public class SellTicket implements Runnable{
	//定義100張票
	private int tickets = 100;
	//定義同一把鎖
	private Object obj = new Object();
	
	@Override
	public void run() {
		while(true){
                        //同步
			synchronized (obj) {
				if(tickets > 0){
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {					
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickets--)+"張票");
				}
			}
		}	
	}
}
package thread;

public class SellTicketDemo {
	public static void main(String[] args) {
		SellTicket st = new SellTicket();
		
		Thread t1 = new Thread(st,"視窗1");
		Thread t2 = new Thread(st,"視窗2");
		Thread t3 = new Thread(st,"視窗3");
		
		t1.start();
		t2.start();
		t3.start();
	}
}

 還可以把同步程式碼塊寫成同步方法,這時鎖物件是這個方法--this。//synchronized (this)

package thread;

public class SellTicket implements Runnable{
	//定義100張票
	private int tickets = 100;
	//定義同一把鎖
	private Object obj = new Object();
	
	@Override
	public void run() {
		while(true){
			sellTicket();			
                }	
	}
	
	private synchronized void sellTicket(){
		if(tickets > 0){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {					
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickets--)+"張票");
		}
	}
}

當方法時靜態時,鎖物件是類的位元組碼檔案物件,即當前類的class檔案。 //synchronized(SellTicket.class)

package thread;

public class SellTicket implements Runnable{
	//定義100張票
	private static int tickets = 100;
	//定義同一把鎖
	private Object obj = new Object();
	
	@Override
	public void run() {
		while(true){
			sellTicket();
		}	
	}
	
	private static synchronized void sellTicket(){
		if(tickets > 0){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {					
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickets--)+"張票");
		}
	}
}

2.使用lock解決執行緒安全問題

package thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SellTicketLock implements Runnable{
	private int tickets = 100;
	private Lock lock = new ReentrantLock();
	
	@Override
	public void run() {
		while(true){
			try{
				lock.lock(); //加鎖
				if(tickets > 0){
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickets--)+"張票");
				}
			}finally{
				lock.unlock();
			}
		}
	}
}

 

package thread;

public class SellTicketDemo {
	public static void main(String[] args) {
		SellTicketLock st = new SellTicketLock();
		
		Thread t1 = new Thread(st,"視窗1");
		Thread t2 = new Thread(st,"視窗2");
		Thread t3 = new Thread(st,"視窗3");
		
		t1.start();
		t2.start();
		t3.start();
	}
}

 把不安全的list集合安全的使用:

List<String> list1 = new ArrayList<String>();   //執行緒不安全
List<String> list2 = Collections.synchronizedList(new ArrayList<String>());  //執行緒安全

三、生產者消費者之等待喚醒機制

package pv;

public class Student {
	private String name;
	private int age;
	private boolean flag;	//預設為false,若為true,則有資料
	
	public synchronized void set(String name,int age){
		//若果有資料,就等待
		if(this.flag){
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		//設定資料
		this.name = name;
		this.age = age;
		//修改標記
		this.flag = true;
		this.notify(); 
	}
	
	public synchronized void get(){
		//如果沒有資料,就等待
		if(!this.flag){
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println(this.name+"---"+this.age);
		this.flag = false;
		this.notify();
	}
}
package pv;

public class Set implements Runnable{
	private Student s;
	private int x = 0;
	
	public Set(Student s){
		this.s = s ;
	}
	@Override
	public void run() {
		while(true){
			if(x % 2 == 0){
				s.set("yj", 23);
			}else{
				s.set("kryie", 25);
			}
			x++;
		}
	}
}
package pv;

public class Get implements Runnable{
	private Student s; 
	
	public Get(Student s){
		this.s = s ;
	}
	@Override
	public void run() {
		while(true){
			s.get();
		}
	}
}
package pv;

public class StudentDemo {
	public static void main(String[] args) {
		//建立資源
		Student s = new Student();
		//設定資源、獲取資源
		Set st = new Set(s);
		Get gt = new Get(s);
		//執行緒類
		Thread t1 = new Thread(st);
		Thread t2 = new Thread(gt);
		//啟動執行緒
		t1.start();
		t2.start();
	}
}