java多線程與同步問題

java 多線程和同步

java 多線程

多線程的作用
  1. 提高資源的利用率
    如果當執行單線程的程序時,程序發生阻塞情況,此時的CPU會處於空閒狀態;而多線程中,當有一個線程發生阻塞時,CPU會執行其他的進程,從而提高了資源的利用率。
  2. 簡化編程
    如果編寫一個讀取和操作文件的程序時,必須跟蹤每個文件的讀取和處理狀態,相反我們可以創建兩個線程,每個線程只讀取或處理單個文件,這樣不僅可以提高磁盤的利用率,還容編寫。、
創建自定義線程的兩種方式
  1. 自定義線程類,繼承Thread類,重寫run方法
    創建自定義線程對象,直接調用start方法,開啓線程
class MyThread1 extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println("繼承Thread類自定義線程類");
		}
	}
}
//在main方法中
MyThread1 myThread1 = new MyThread1();
myThread1.start();
  1. 自定義線程類,遵從Runnable接口
    使用自定義遵從接口Runnable實現類對象,作爲Thread構造方法參數,藉助於Thread類對象和start方法,開啓線程
class MyThread2 implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println("遵從Runnable接口實現自定義線程類");
		}
	}
}
//在main方法中
Thread thread = new Thread(new MyThread2());
// 藉助於Thread類內的start方法開啓線程
thread.start();
Thread 中的方法
構造方法名 作用
Thread() 無目標,無指定名字
Thread(Runnable target); 創建線程對象的過程中,使用Runnable接口的實現類
Thread(String name); 無目標,有名字
Thread(Runnable target, String name); 使用Runnable接口實現類對象,作爲執行目標,並且指定name作爲線程名
成員方法 作用
void setName(String name);String getName(); name的getter 和 Setter 方法
void setPriority(int Priority); 設置線程的優先級 [1 ~ 10]
int getPriority(); 獲取線程優先級
void start(); 啓動線程對象
public static void sleep(int ms); 對應進程進行休眠操作。單位毫秒
public static Thread currentThread(); 獲取當前所處代碼塊對應的線程對象

線程安全問題和解決方案

舉例來說,一個電影有100張票,有3個出售平臺,實現這個案例

class SingleThread implements Runnable {
	private static int ticket = 100;
	@Override
 	public void run() {
 		while (true) {
 		// a
			if (ticket > 0) {
				System.out.println(Thread.currentThread().getName() + "售出了" + ticket + "張票");
				ticket -= 1;
				try {
				     Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} else {
				System.out.println(Thread.currentThread().getName() + "售罄!");
				break;
			}
		//b
		}
 	}
}
//在main方法中
Thread thread1 = new Thread(new SingleThread(), "淘票票");
Thread thread2 = new Thread(new SingleThread(), "貓眼");
Thread thread3 = new Thread(new SingleThread(), "美團");

thread1.start();
thread2.start();
thread3.start();

但是在運行的結果中,我們會發現同一張票被出售了不止一次,爲了解決這種問題,我們引入了“鎖”機制。

synchronized
while (true) {
	synchronized("鎖") {
		//此處是上面的ab範圍內的代碼
	}
}

通過這種方式我們可以解決上面出現的問題

三種加鎖的方式
  1. 同步方法由static修飾,所以在main方法中可以使用多個目標
    在這裏插入圖片描述
//main方法中
Thread thread1 = new Thread(new SingleThread3(), "淘票票");
Thread thread2 = new Thread(new SingleThread3(), "貓眼");
Thread thread3 = new Thread(new SingleThread3(), "美圖");

thread1.start();
thread2.start();
thread3.start();
  1. 同步方法是非靜態成員方法時,這個時候只能使用單目標

在這裏插入圖片描述

// main方法中
SingleThread2 singleThread2 = new SingleThread2();

Thread thread1 = new Thread(singleThread2, "淘票票");
Thread thread2 = new Thread(singleThread2, "貓眼");
Thread thread3 = new Thread(singleThread2, "美圖");

thread1.start();
thread2.start();
thread3.start();
  1. Lock 鎖
private static int ticket = 100;
//定義一個成員變量
static Lock lock = new ReentrantLock();
@Override
public void run() {
	while (true) {
		//在 a 的位置添加
		lock.lock();
		/*
		* ab之間的代碼
		*/
		lock.unlock();
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章