Java使用Thread類代表線程,所有線程都是Thread類或其子類哩照,Java創(chuàng)建線程的方式有4種,它們分別是:
1椰棘、繼承Thread類創(chuàng)建線程纺棺;
2、實現Runable接口創(chuàng)建線程(首推)邪狞;
3祷蝌、使用Callable和Future創(chuàng)建線程;
4帆卓、使用線程池巨朦,例如Executor框架。
注意:call()方法有返回值鳞疲,run()方法沒有罪郊。
方式1:Thread
public class MyThread extends Thread {
public void run(){
System.out.println("線程");
}
}
public class MainTest {
public static void main(String[] args){
new MyThread().start();
}
}
方式2:Runnable
public class MyThread implements Runnable {
public void run(){
System.out.println("線程Runnable");
}
}
public class MainTest {
public static void main(String[] args){
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
}
}
或者直接寫線程的實現
public class MainTest {
public static void main(String[] args){
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("創(chuàng)建線程方式二");
}
}).start();
}
}
方式3:Callable或者Future
public class CallableTest implements Callable<Integer> {
@Override
public Integer call() throws Exception {
// 計算1-100的和
int sum = 0;
for (int i = 1; i <= 100; i++)
sum += i;
return sum;
}
}
public class MainTest {
public static void main(String[] args) {
CallableTest cd = new CallableTest();
// 使用Callable方式創(chuàng)建線程,需要FutureTask類的支持尚洽,用于接收運算結果悔橄,可以使用泛型指定返回值的類型
FutureTask<Integer> result = new FutureTask<>(cd);
new Thread(result).start();
int sum = 0;
// 接收運算結果
// 只有當該線程執(zhí)行完畢后才會獲取到運算結果,等同于閉鎖的效果
try {
sum = result.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("sum is " + sum);
}
}
方式4:Executor框架
Executor框架包括:線程池腺毫,Executor癣疟,Executors,ExecutorService潮酒,CompletionService睛挚,Future,Callable等
ExecutorService的生命周期包括三種狀態(tài):運行急黎、關閉扎狱、終止。創(chuàng)建后便進入運行狀態(tài)勃教,當調用了shutdown()方法時淤击,便進入關閉狀態(tài),此時意味著ExecutorService不再接受新的任務故源,但它還在執(zhí)行已經提交了的任務污抬,當素有已經提交了的任務執(zhí)行完后,便到達終止狀態(tài)绳军。
Executors提供了一系列工廠方法用于創(chuàng)建線程池印机,返回的線程池都實現了ExecutorService接口
1、創(chuàng)建固定數目線程的線程池
public static ExecutorService newFixedThreadPool(int nThreads)
2门驾、創(chuàng)建可緩存的線程池
public static ExecutorService newCachedThreadPool()
3射赛、創(chuàng)建一個單線程化的Executor
public static ExecutorService newSingleThreadExecutor()
4、創(chuàng)建一個支持定時及周期性的任務執(zhí)行的線程池奶是,多數情況下可用來替代Timer類
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
Executor執(zhí)行Runable任務示例:
public class MainTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
// ExecutorService executorService = Executors.newFixedThreadPool(5);
// ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++){
executorService.execute(new TestRunnable());
System.out.println("************* a" + i + " *************");
}
executorService.shutdown();
}
}
class TestRunnable implements Runnable{
public void run(){
System.out.println(Thread.currentThread().getName() + "線程被調用了咒劲。");
}
}
public class MainTest {
private ExecutorService pool;
@PostConstruct
public void init(){
//自定義線程工廠
pool = new ThreadPoolExecutor(5, 10, 1000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(20),
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
//線程命名
Thread th = new Thread(r,"threadPool"+r.hashCode());
return th;
}
},new ThreadPoolExecutor.CallerRunsPolicy());
}
public void test(){
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "線程被調用了顷蟆。");
}
});
}
}
Executor實現Callable任務示例:
public class MainTest {
public static void main(String[] args){
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<String>> resultList = new ArrayList<Future<String>>();
//創(chuàng)建10個任務并執(zhí)行
for (int i = 0; i < 10; i++){
//使用ExecutorService執(zhí)行Callable類型的任務,并將結果保存在future變量中
Future<String> future = executorService.submit(new TaskWithResult(i));
//將任務執(zhí)行結果存儲到List中
resultList.add(future);
}
//遍歷任務的結果
for (Future<String> fs : resultList){
try{
while(!fs.isDone());//Future返回如果沒有完成腐魂,則一直循環(huán)等待,直到Future返回完成
System.out.println(fs.get()); //打印各個線程(任務)執(zhí)行的結果
}catch(InterruptedException e){
e.printStackTrace();
}catch(ExecutionException e){
e.printStackTrace();
}finally{
//啟動一次順序關閉逐纬,執(zhí)行以前提交的任務蛔屹,但不接受新任務
executorService.shutdown();
}
}
}
}
class TaskWithResult implements Callable<String>{
private int id;
public TaskWithResult(int id){
this.id = id;
}
/**
* 任務的具體過程,一旦任務傳給ExecutorService的submit方法豁生,
* 則該方法自動在一個線程上執(zhí)行
*/
public String call() throws Exception {
System.out.println("call()方法被自動調用M枚尽!甸箱! " + Thread.currentThread().getName());
//該返回結果將被Future的get方法得到
return "call()方法被自動調用育叁,任務返回的結果是:" + id + " " + Thread.currentThread().getName();
}
}
自定義線程池
自定義線程池,可以用ThreadPoolExecutor類創(chuàng)建芍殖,它有多個構造方法來創(chuàng)建線程池豪嗽,用該類很容易實現自定義的線程池
public class MainTest {
public static void main(String[] args){
//創(chuàng)建等待隊列
BlockingQueue<Runnable> bqueue = new ArrayBlockingQueue<Runnable>(20);
//創(chuàng)建線程池,池中保存的線程數為3豌骏,允許的最大線程數為5
ThreadPoolExecutor pool = new ThreadPoolExecutor(3,5,50,TimeUnit.MILLISECONDS,bqueue);
//創(chuàng)建七個任務
Runnable t1 = new MyThread1();
Runnable t2 = new MyThread1();
Runnable t3 = new MyThread1();
Runnable t4 = new MyThread1();
Runnable t5 = new MyThread1();
Runnable t6 = new MyThread1();
Runnable t7 = new MyThread1();
//每個任務會在一個線程上執(zhí)行
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
pool.execute(t6);
pool.execute(t7);
//關閉線程池
pool.shutdown();
}
}
class MyThread1 implements Runnable{
@Override
public void run(){
System.out.println(Thread.currentThread().getName() + "正在執(zhí)行龟梦。。窃躲。");
try{
Thread.sleep(100);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}