JAVA控制線程并發(fā)數(shù)量方法主要有耀销,限制一個線程使用(synchronized),限制指定數(shù)量的線程并發(fā)使用(Semaphore)
一、JAVA控制線程主要有限制當(dāng)前方法只能被一個線程訪問,方法主要為:synchronized(),當(dāng)一個方法用synchronized修飾之后焚挠,該方法就只能被一個線程使用膏萧,等于此方法的門上了一道鎖,其他線程需要在“門”外等待蝌衔,直到里面的線程出來了才可以繼續(xù)訪問榛泛。我們來看案例一體會一下。
案例一:顧客進(jìn)服裝店的購物過程包含三個環(huán)節(jié)噩斟,選衣服曹锨,試衣服,結(jié)賬離開剃允。其中選衣服環(huán)節(jié)和試衣服環(huán)節(jié)需要的時間為 10-30分鐘不等(隨機(jī))沛简,結(jié)賬離開環(huán)節(jié)5分鐘,該店只有一間試衣間(不能兩人同時使用)斥废。 請編寫一個程序模擬2個顧客進(jìn)店購買的過程椒楣。程序執(zhí)行過程中,輸出每個顧客所處的環(huán)節(jié)信息牡肉。 比如捧灰,顧客1在試衣服,顧客2统锤,在選衣服毛俏,顧客2在試衣服炭庙。
代碼:
import java.util.Random;
public class ClothesShop implements Runnable{
ClothesShop(){
}
public void selectclothes() {
long time = (long)(Math.random()*20 + 10);
System.out.println("顧客" + Thread.currentThread().getName() + "正在選擇衣服, " + "時間為:" + time + " s");
try {
Thread.sleep(time*1000);
}catch(Exception e) {
e.printStackTrace();
}
}
//用synchronized修飾,此方法只能被一個線程使用
public synchronized void tryclothes() {
long time = (long)(Math.random()*20 + 10);
System.out.println("顧客" + Thread.currentThread().getName() + "試衣服, " + "時間為:" + time + " s");
try {
Thread.sleep(time*1000);
}catch(Exception e) {
e.printStackTrace();
}
}
public void givemoney() {
long time = 5;
System.out.println("顧客" + Thread.currentThread().getName() + "正在結(jié)賬, " + "時間為:" + time + " s");
try {
Thread.sleep(time*1000);
}catch(Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true) {
selectclothes();
tryclothes();
givemoney();
break;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ClothesShop clothesshop = new ClothesShop();
Thread c1 = new Thread(clothesshop,"1");
Thread c2 = new Thread(clothesshop,"2");
c1.start();
c2.start();
}
}
二煌寇、JAVA控制指定線程數(shù)量并發(fā)主要是采用Semaphore()方法焕蹄。當(dāng)并發(fā)線程數(shù)量達(dá)到限定數(shù)量時,就會給該方法的“門”上鎖唧席,直到一個線程出來擦盾,釋放了并發(fā)線程數(shù)量,其他線程才能繼續(xù)訪問這個方法淌哟,進(jìn)入這道“門”迹卢。我們直接看案例體會一下:
案例二:案例一改編:如果有2個試衣間,同一時間只能容納5個乘客進(jìn)店購物徒仓,選衣服和試衣服的時間都是隨機(jī)的腐碱,請編程模擬。
代碼:
import java.util.Random;
import java.util.concurrent.Semaphore;
public class ClothesShop2 implements Runnable{
private static Semaphore msemaphoretryroom = new Semaphore(2);//指定線程并發(fā)數(shù)量
private static Semaphore msemaphoreshoproom = new Semaphore(5);
ClothesShop2(){
}
public void selectclothes() {
try {
msemaphoreshoproom.acquire();//shoproom可用數(shù)量減少
} catch (Exception e) {
e.printStackTrace();
}
//availablePermits()查看當(dāng)前可用的并發(fā)數(shù)數(shù)量
//System.out.println(msemaphoreshoproom.availablePermits());
System.out.println("顧客" + Thread.currentThread().getName() + "進(jìn)來商店了");
long time = (long)(Math.random()*20 + 10);
System.out.println("顧客" + Thread.currentThread().getName() + "正在選擇衣服, " + "時間為:" + time + " s");
try {
Thread.sleep(time*1000);
}catch(Exception e) {
e.printStackTrace();
}
}
//用synchronized修飾掉弛,此方法只能被一個線程使用
public void tryclothes() {
try {
msemaphoretryroom.acquire();//tryroom可用數(shù)量減少
} catch (Exception e) {
e.printStackTrace();
}
long time = (long)(Math.random()*20 + 10);
System.out.println("顧客" + Thread.currentThread().getName() + "試衣服, " + "時間為:" + time + " s");
try {
Thread.sleep(time*1000);
}catch(Exception e) {
e.printStackTrace();
}
msemaphoretryroom.release();//一個線程從tryroom中出來症见,釋放tryroom數(shù)量
}
public void givemoney() {
long time = 5;
System.out.println("顧客" + Thread.currentThread().getName() + "正在結(jié)賬, " + "時間為:" + time + " s");
try {
Thread.sleep(time*1000);
}catch(Exception e) {
e.printStackTrace();
}
msemaphoreshoproom.release();//釋放shoproom數(shù)量
System.out.println("顧客" + Thread.currentThread().getName() + "出去商店了");
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true) {
selectclothes();
tryclothes();
givemoney();
break;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ClothesShop2 clothesshop = new ClothesShop2();
for(int i = 1; i <= 10; i++) {
Thread c = new Thread(clothesshop,String.valueOf(i));
c.start();
}
}
}