定義線程類
1. 實(shí)現(xiàn)Runnable接口
public class Liftoff implements Runnable {
private int countDown = 10;
private static int taskCount = 0;
private final int id = taskCount++;
private String status() {
return "#" + id + "(" + (countDown > 0 ? countDown : "Liftoff!") + "), ";
}
public void run() {
while (countDown-- > 0) {
System.out.print(status());
Thread.yield();
}
}
}
2. 使用Thread類
public class BasicThreads {
public static void main(String[] args) {
Thread t1 = new Thread(new LiftOff());
t1.start();
Thread t2 = new Thread(new LiftOff());
t2.start();
System.out.println("Waiting for LiftOff");
}
}
- 缺點(diǎn):繼承Thread導(dǎo)致無法繼承其他類末贾,而實(shí)現(xiàn)Runnable接口的方式還能繼承其他類
代碼
public class SimpleThread extends Thread {
private int countDown = 5;
private static int threadCount = 0;
private SimpleThread() {
super(Integer.toString(++threadCount));
start();
}
public String toString() { return "#" + getName() + "(" + countDown + "), "; }
public void run() {
while (true) {
System.out.print(this);
if (--countDown == 9) return;
}
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new SimpleThread();
}
}
}
創(chuàng)建無限線程的線程池
public class CachedThreadPool {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++)
exec.execute(new LiftOff());
exec.shutdown();
}
}
創(chuàng)建有限線程的線程池
public class FixedThreadPool {
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++)
exec.execute(new LiftOff());
exec.shutdown();
}
}
創(chuàng)建單一線程
public class SingleThreadExecutor {
public static void main(String[] args) {
ExecutorService exec = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++)
exec.execute(new LiftOff());
exec.shutdown();
}
}
- 相比Runnable接口易迹,Callable接口可以從線程中返回一個(gè)值袍嬉,這個(gè)值通過Future對象包裝
class TaskWithResult implements Callable<String> {
private int id;
TaskWithResult(int id) { this.id = id; }
public String call() { return "result of TaskWithResult " + id; }
}
public class CallableDemo {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(exec.submit(new TaskWithResult(i)));
}
for (Future<String> fs : results) {
try {
// get會阻塞程序
System.out.println(fs.get());
} catch (InterruptedException e) {
e.printStackTrace();
return;
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
exec.shutdown();
}
}
}
}
休眠
方式一
Thread.sleep(100);
方式二
TimeUnit.MILLISECONDS.sleep(100);
線程優(yōu)先級
public class SimplePriorities implements Runnable {
private int countDown = 5;
private int priority;
private SimplePriorities(int priority) {
this.priority = priority;
}
public void run() {
// 設(shè)置優(yōu)先級
Thread.currentThread().setPriority(priority);
while (true) {
for (int i = 1; i < 100000; i++) {
if (i % 1000 == 0) {
Thread.yield();
}
}
if (--countDown == 0) {
return;
}
}
}
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
exec.execute(new SimplePriorities(Thread.MIN_PRIORITY));
}
exec.execute(new SimplePriorities(Thread.MAX_PRIORITY));
exec.shutdown();
}
}
后臺線程
描述
- 當(dāng)程序所有非后臺線程中止時(shí)丈钙,后臺線程會被殺死陈惰。
- 通常后臺線程程序中不是不可或缺的部分疏咐。
- 后臺線程創(chuàng)建的線程也是后臺線程扬舒。
簡單示例
public class SimpleDaemons implements Runnable {
public void run() {
try {
while (true) {
TimeUnit.MILLISECONDS.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] arms) throws Exception {
for (int i = 0; i < 10; i++) {
Thread daemon = new Thread(new SimpleDaemons());
// 設(shè)置此線程為后臺線程
daemon.setDaemon(true);
daemon.start();
}
TimeUnit.MILLISECONDS.sleep(175);
}
}
// 通過實(shí)現(xiàn)ThreadFactory接口來實(shí)現(xiàn)創(chuàng)建線程時(shí)的預(yù)處理
class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(@NotNull Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
}
public class DaemonThread implements Runnable {
public void run() {
try {
while (true) {
TimeUnit.MILLISECONDS.sleep(100);
}
} catch (InterruptedException e) {
System.out.print("Interrupted");
}
}
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool(new DaemonThreadFactory());
for (int i = 0; i < 10; i++)
exec.execute(new DaemonThread());
TimeUnit.MILLISECONDS.sleep(500);
}
}
線程交互
- 有線程A和線程B阐肤,若在線程A中調(diào)用B.join(),則線程A會在此處掛起直至線程B結(jié)束呼巴。
- 有線程A和線程B泽腮,若在線程A中調(diào)用B.interrupt()御蒲,則線程B會中斷并拋出異常。
異常處理器
class ExceptionThread implements Runnable {
public void run() {
Thread t = Thread.currentThread();
throw new RuntimeException();
}
}
// 實(shí)現(xiàn)接口Thread.UncaughtExceptionHandler作為異常處理器
class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
System.out.println("ViAritcPtiln'e");
}
}
class HandlerThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
// 每個(gè)線程都綁定一個(gè)異常處理器
t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
return t;
}
}
public class CaptureUncaughtException {
public static void main(String[] args) {
// 設(shè)置默認(rèn)線程處理器
// Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
ExecutorService exec = Executors.newCachedThreadPool(new HandlerThreadFactory());
exec.execute(new ExceptionThread());
}
}