自從java1.5以后,官網(wǎng)就推出了Executor這樣一個(gè)類(lèi),這個(gè)類(lèi)定血,可以維護(hù)我們的大量線程在操作臨界資源時(shí)的穩(wěn)定性。
先上一段代碼吧:
TestRunnable.java
public class TestRunnable implements Runnable {
private String name;
public TestRunnable(String name) {
this.name = name;
}
@Override
public void run() {
while (true) {
if (Main.Surplus < 0)
return;
Main.Surplus--;
System.out.println(name + " " + Main.Surplus);
}
}
}
main入口
public static void main(String[] args) {
TestRunnable runnable = new TestRunnable("runnable1");
TestRunnable runnable2 = new TestRunnable("runnable2");
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable2);
t1.start();
t2.start();
}
這樣诞外,我們就看到了澜沟,數(shù)據(jù)肯定是亂了的,當(dāng)然這個(gè)時(shí)候我們可以加上一個(gè)synchronized的關(guān)鍵字峡谊,但是這樣也會(huì)出現(xiàn)點(diǎn)小問(wèn)題的
下面我打算采用一種java內(nèi)置的線程管理的機(jī)制茫虽,來(lái)解決這個(gè)問(wèn)題,解決這個(gè)問(wèn)題的思路大概就是靖苇,我們維護(hù)了一個(gè)線程池席噩,當(dāng)有請(qǐng)求操作的時(shí)候統(tǒng)統(tǒng)進(jìn)入線程池,并且我們只開(kāi)了一個(gè)線程贤壁,可以讓請(qǐng)求順序執(zhí)行悼枢,順序調(diào)用臨界資源,就很安全了脾拆。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main {
public static int Surplus = 10;
private ExecutorService executor = Executors.newSingleThreadExecutor();
void addTask(Runnable runnable) {
executor.execute(runnable);
}
<V> V addTask(Callable<V> callable) {
Future<V> submit = executor.submit(callable);
try {
return submit.get();
} catch (InterruptedException e) {
System.out.println("InterruptedException" + e.toString());
} catch (ExecutionException e) {
System.out.println("ExecutionException" + e.toString());
}
return null;
}
public void testAddTask(String name) {
addTask(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
if (Main.Surplus <= 0)
return;
Main.Surplus--;
System.out.println(name + " " + Main.Surplus);
}
}
});
}
public void testAddTask2(String name) {
int count = addTask(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
for (int i = 0; i < 3; i++) {
if (Main.Surplus <= 0)
return 0;
Main.Surplus--;
System.out.println(name + " " + Main.Surplus);
}
return Main.Surplus;
}
});
}
public void close() {
executor.shutdown();
}
public static void main(String[] args) {
Main main = new Main();
main.testAddTask("task1");
main.testAddTask2("task2");
main.testAddTask("task3");
main.testAddTask2("task4");
main.close();
}
}
在這里馒索,我們定義了兩種方法莹妒,分別是addTask,具有泛型的addTask绰上,這兩種方法實(shí)現(xiàn)原理都是一樣的旨怠,其中一個(gè)是有回調(diào)的,一個(gè)是沒(méi)有回調(diào)的蜈块,就看項(xiàng)目需求了吧鉴腻。
然后分別調(diào)用這兩個(gè)方法咯,就可以看到結(jié)果是非常有序百揭,且不會(huì)混亂的爽哎。
當(dāng)然啊,系統(tǒng)為我們提供這樣一個(gè)類(lèi)器一,肯定不是為了實(shí)現(xiàn)這么小的一個(gè)功能的课锌,它還有很多功能,我也在進(jìn)一步的學(xué)習(xí)中~