日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java执行程序默认多线程吗_Java多线程 执行程序(1)

發(fā)布時(shí)間:2024/7/5 java 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java执行程序默认多线程吗_Java多线程 执行程序(1) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文由作者收集整理所得,作者不保證內(nèi)容的正確行,轉(zhuǎn)載請(qǐng)標(biāo)明出處。

作者:關(guān)新全

Java多線程

執(zhí)行程序(1)

1.1

Thread類

static Thread.currentThread

返回當(dāng)前正在執(zhí)行的線程對(duì)象的引用。

join 等待線程終止。

yield 暫停當(dāng)前正在執(zhí)行的線程對(duì)象,并執(zhí)行其他線程。

Demo1-1中給出的程序中,主函數(shù)中創(chuàng)建了兩個(gè)線程,每個(gè)子線程第一條輸出語句執(zhí)行結(jié)束后,放棄了執(zhí)行權(quán),從而讓其他線程有機(jī)會(huì)繼續(xù)執(zhí)行。這樣就會(huì)看到子線程1和子線程2交叉輸出的信息。在主線程中使用了join方法,阻塞等待子線程執(zhí)行結(jié)束,當(dāng)兩個(gè)子線程將其內(nèi)部的信息全部輸出后,主線程才將其線程線性輸出。(Thread.currentThread的輸出格式為,[子線程名,線程優(yōu)先級(jí),線程組名])。最后,在main函數(shù)內(nèi)部需要調(diào)用內(nèi)部類,內(nèi)部類應(yīng)當(dāng)為static。一般情況下,內(nèi)部類和內(nèi)部接口都應(yīng)當(dāng)是static的。

Demo 1-1 Thread

類的用法

package com.upc.upcgrid.guan.advancedJava.chapter02;

public class YieldTest {

public static class ThreadImpl implements Runnable{

@Override

public void run() {

System.err.println(Thread.currentThread());

Thread.yield();

System.err.println(Thread.currentThread());

}

}

public static void main(String[] args) throws InterruptedException {

Thread t1 = new Thread(new ThreadImpl());

Thread t2 = new Thread(new ThreadImpl());

t1.start();

t2.start();

t1.join();

t2.join();

System.err.println(Thread.currentThread());

}

}

Demo1-1 輸出結(jié)果

Thread[Thread-0,5,main]

Thread[Thread-1,5,main]

Thread[Thread-0,5,main]

Thread[Thread-1,5,main]

Thread[main,5,main]

1.2 Executor

接口

Executor可以定制創(chuàng)建特殊的子線程。例如,在創(chuàng)建一系列的子線程時(shí),對(duì)子線程進(jìn)行同樣的配置,如果,需要修改或增強(qiáng)子線程的開啟或配置,只需修改Executor的實(shí)現(xiàn)即可。

在Demo1-2中,主線程通過Executor接口創(chuàng)建和執(zhí)行一個(gè)新的線程。在Executor接口的ExecutorInterface實(shí)現(xiàn)中,可以對(duì)所有的線程進(jìn)行一些默認(rèn)的配置,然后啟動(dòng)執(zhí)行這個(gè)線程。如果,此時(shí)我們需要修改這個(gè)系列線程的優(yōu)先級(jí),只需要修改ExecutorInterface接口中的相應(yīng)值即可,無需修改代碼中的所有創(chuàng)建線程的地方。(有時(shí)可以在Executor的executor的方法實(shí)現(xiàn)中使用一定的線程調(diào)度策略,這樣可以為線程調(diào)度提供靈活性,當(dāng)修改線程調(diào)度的實(shí)現(xiàn)時(shí),不影響外部使用的代碼)。

Demo1-3實(shí)現(xiàn)了一個(gè)線程優(yōu)先隊(duì)列的Executor,在這樣的Executor中,每次提交的任務(wù)會(huì)被放入一個(gè)隊(duì)列中,Executor最多只開啟一個(gè)線程執(zhí)行這個(gè)隊(duì)列中的任務(wù),而且隊(duì)列使用優(yōu)先級(jí)策略,就是優(yōu)先級(jí)高的線程將會(huì)先被Executor執(zhí)行,優(yōu)先級(jí)低的線程將需等待優(yōu)先級(jí)高的線程執(zhí)行結(jié)束后,才能獲得執(zhí)行權(quán)。從代碼中看出,創(chuàng)建了5個(gè)線程,設(shè)置了不同的優(yōu)先級(jí),并提交個(gè)Executor去執(zhí)行。從執(zhí)行結(jié)果可以看出,線程基本是按照線程優(yōu)先級(jí)次序執(zhí)行的(線程優(yōu)先級(jí)5先執(zhí)行,因?yàn)樵谒峤坏臅r(shí)候隊(duì)列中并沒有其他線程,他的優(yōu)先級(jí)最高,因此它被最先執(zhí)行了,也就是說這個(gè)優(yōu)先級(jí)還與線程的提交次序有關(guān))。Executor更傾向于開啟一個(gè)線程,在稍后對(duì)ExecutorFactory介紹時(shí),可以看出,他們一個(gè)是執(zhí)行線程,一個(gè)是創(chuàng)建線程。

Demo 1-2

Executor接口的使用

package com.upc.upcgrid.guan.SpecialUse.chapter01;

import java.lang.Thread.UncaughtExceptionHandler;

import java.util.concurrent.Executor;

public class ExecutorInterface implements Executor{

@Override

public void execute(Runnable command) {

Thread t = new Thread(command);

t.setDaemon(false);

t.setPriority(6);

t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {

@Override

public void uncaughtException(Thread t, Throwable e)

{

System.err.println(e.getMessage());

}

});

t.start();

}

private static class RunnableImpl implements Runnable{

@Override

public void run() {

System.err.println(Thread.currentThread());

}

}

public static void main(String[] args) throws InterruptedException {

ExecutorInterface e = new ExecutorInterface();

e.execute(new RunnableImpl());

e.execute(new RunnableImpl());

}

}

Demo1-3 線程池的初探

package com.upc.upcgrid.guan.SpecialUse.chapter01;

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.Executor;

import java.util.concurrent.PriorityBlockingQueue;

public class ExecutorInterfaceWithSchedule

implements Executor{

private BlockingQueue

queue = new PriorityBlockingQueue();

private Thread t;

public ExecutorInterfaceWithSchedule() {

Thread inner =new Thread(new Runnable() {

@Override

public void run() {

try {

while(true)

{

t = new Thread(queue.take());

t.start();

t.join();//等待線程結(jié)束

}

} catch (InterruptedException e) {

}

}

});

inner.setDaemon(true);

inner.start();

}

@Override

public void execute(Runnable command) {

try {

queue.put(command);

} catch (InterruptedException e) {

}

}

private static class ThreadImpl implements Runnable,Comparable{

public int priority;

public ThreadImpl(int priority) {

this.priority = priority;

}

@Override

public void run() {

System.err.println(Thread.currentThread() +

String.valueOf(priority));

}

@Override

public int compareTo(ThreadImpl o) {

return o.priority > priority?1:0;

}

}

public static void main(String[] args) throws InterruptedException {

ThreadImpl t1 = new ThreadImpl(5);

ThreadImpl t2 = new ThreadImpl(6);

ThreadImpl t3 = new ThreadImpl(7);

ThreadImpl t4 = new ThreadImpl(1);

ThreadImpl t5 = new ThreadImpl(4);

ExecutorInterfaceWithSchedule executor = new ExecutorInterfaceWithSchedule();

executor.execute(t1);

executor.execute(t2);

executor.execute(t3);

executor.execute(t4);

executor.execute(t5);

Thread.sleep(10000);

}

}

Demo1-3執(zhí)行結(jié)果:

Thread[Thread-1,5,main]5

Thread[Thread-2,5,main]7

Thread[Thread-3,5,main]6

Thread[Thread-4,5,main]4

Thread[Thread-5,5,main]1

Graphic 1-1

與Executor有關(guān)的接口

1.3

ExecutorService接口

ExecutorService接口用于管理Executor接口,用于跟蹤一個(gè)和多個(gè)異步任務(wù)的執(zhí)行。簡(jiǎn)單的說就是提供一個(gè)線程池的功能,可以向線程池中提交多個(gè)任務(wù),線程池根據(jù)具體的實(shí)現(xiàn),采用一定的調(diào)度方法和策略對(duì)提交的線程進(jìn)行排隊(duì)和執(zhí)行。

ExecutorService提供了shutDown方法,可以終止線程池繼續(xù)接受新的任務(wù),使用shutDown方法并不會(huì)立即取消正在執(zhí)行的任務(wù),他會(huì)在線程任務(wù)執(zhí)行結(jié)束后,自動(dòng)關(guān)閉并釋放線程資源。shutDownNow方法則不同,線程池會(huì)嘗試試圖關(guān)閉正在執(zhí)行的線程。

Submit擴(kuò)展了Executor接口的executor方法,并返回一個(gè)Future,用來取消或查詢線程任務(wù)。invokeAll和invokeAny方法是批量執(zhí)行任務(wù)的常見形式。invokeAll是等待所有任務(wù)結(jié)束才返回,而invokeAny是其中有一個(gè)任務(wù)完成就返回。

一般通過Executors類的靜態(tài)函數(shù)來創(chuàng)建相應(yīng)的ExecutorService實(shí)例。

Demo 1-4中,主線程先創(chuàng)建了十個(gè)任務(wù),然后將這十個(gè)任務(wù)的集合提交給線程池執(zhí)行,線程池的大小是3,線程池根據(jù)內(nèi)部的調(diào)度策略去調(diào)度執(zhí)行任務(wù),從最終的輸出可以看出,線程池的子線程1執(zhí)行的任務(wù)最多。最終在主線程中進(jìn)行結(jié)果統(tǒng)計(jì),關(guān)閉線程池。需要注意的是,線程池的關(guān)閉需要手動(dòng)代碼,而且還要給出出錯(cuò)的情況下如何合理的終結(jié)線程池。

Demo 1-4 線程池的使用:

package com.upc.upcgrid.guan.SpecialUse.chapter01;

import java.util.ArrayList;

import java.util.List;

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;

import java.util.concurrent.TimeUnit;

public class ExecuteServiceInterface {

public static final int THREAD_SIZE = 10;

private static class onceCompute implements Callable{

private int start;

private int end;

public onceCompute(int start,int end) {

this.start = start;

this.end = end;

}

@Override

public Integer call() throws Exception {

int sum = 0;

for(int i = start ; i < end ; i++)

{

sum += i;

}

System.err.println(Thread.currentThread());

return sum;

}

}

public static void main(String[] args) throws InterruptedException, ExecutionException

{

ExecutorService pool =

Executors.newFixedThreadPool(3);//創(chuàng)建3個(gè)線程的線程池

List>

calls = new ArrayList>();//任務(wù)集合

for(int i = 0 ; i < THREAD_SIZE ;i++)//創(chuàng)建任務(wù)

{

calls.add(new onceCompute(i*100, (i+1)*100));

}

List>

futures = pool.invokeAll(calls);//阻塞等待任務(wù)完成

int sum = 0;

for(Future f :

futures)//匯總?cè)蝿?wù)計(jì)算結(jié)果

{

sum +=f.get();

}

System.out.println(sum);//輸出結(jié)果

//線程池的關(guān)閉策略

pool.shutdown();

try {

pool.awaitTermination(1000, TimeUnit.MILLISECONDS);

} catch (InterruptedException e) {

pool.shutdownNow();

Thread.currentThread().interrupt();

}

}

}

Demo 1-4 的執(zhí)行結(jié)果:

Thread[pool-1-thread-1,5,main]

Thread[pool-1-thread-1,5,main]

Thread[pool-1-thread-1,5,main]

Thread[pool-1-thread-1,5,main]

Thread[pool-1-thread-2,5,main]

Thread[pool-1-thread-3,5,main]

Thread[pool-1-thread-2,5,main]

Thread[pool-1-thread-1,5,main]

Thread[pool-1-thread-2,5,main]

Thread[pool-1-thread-3,5,main]

499500

1.4

ScheduleExecutorService

從Graphic1-1可以看出ScheduleExecutorService是繼承于ExecutorService的一個(gè)增強(qiáng)的接口。這個(gè)接口在ExecutorService接口的基礎(chǔ)上增加了四個(gè)操作,可以分為三種類型,一種類型是schedule函數(shù),用于在指定延時(shí)后創(chuàng)建一個(gè)線程執(zhí)行某項(xiàng)任務(wù),一種是scheduleAtFixedRate在指定延時(shí)后,創(chuàng)建一個(gè)周期性執(zhí)行的線程任務(wù),還有一種是scheduleWithFixedDelay,在指定延時(shí)后以一定的延時(shí)執(zhí)行線程任務(wù)。第二和第三種的區(qū)別在于,第二種計(jì)算的是周期,這個(gè)時(shí)間間隔是指定好的。第三種是延時(shí),是指從一次執(zhí)行結(jié)束,到下一次執(zhí)行開始的這段時(shí)間,這種方式將線程執(zhí)行的時(shí)間也考慮在內(nèi)。

Demo 1-5 給出了這個(gè)示例,每個(gè)1s中輸出當(dāng)前時(shí)間。

Demo1-5 定期任務(wù)

package com.upc.upcgrid.guan.SpecialUse.chapter01;

import java.text.DateFormat;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

public class ScheduleExecutorServiceInterface {

public static void main(String[] args) throws InterruptedException {

ScheduledExecutorServicepool =

Executors.newSingleThreadScheduledExecutor();

pool.scheduleAtFixedRate(new Runnable() {

DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

@Override

public void run() {

System.err.println(df.format(new Date()));

}

}, 1000,1000,TimeUnit.MILLISECONDS);

Thread.sleep(10000);

pool.shutdownNow();

}

}

1.5

ThreadFactory接口

這個(gè)接口用于創(chuàng)建一個(gè)新的線程,它與Executor接口的區(qū)別在于,Executor接口更強(qiáng)調(diào)的是執(zhí)行和管理一個(gè)線程,而ThreadFactory強(qiáng)調(diào)的是如何創(chuàng)建一個(gè)線程。在很多的Executor實(shí)現(xiàn)中,需要提供一個(gè)ThreadFactory實(shí)例,畢竟Executor類中使用new方法創(chuàng)建一個(gè)線程是不合理的,因?yàn)槿绻脩魧?duì)新線程的配置進(jìn)行更改,這種更改將會(huì)被延伸到Executor接口的所有實(shí)現(xiàn)子類,這不利于代碼的擴(kuò)展。ThreadFactory僅有一個(gè)方法newThread,實(shí)現(xiàn)這個(gè)方法,用于創(chuàng)建自己的線程邏輯。

Demo1-6中,ThreadFactory用來指定創(chuàng)建多線程的方式,定制多線程的創(chuàng)建方法,而Executor則更強(qiáng)調(diào)如何執(zhí)行,如何管理多線程。所以,在Executor類中應(yīng)當(dāng)有一個(gè)ThreadFactory引用,這樣在Executor類中就無需顯示使用new,并且負(fù)責(zé)與線程相關(guān)的配置,當(dāng)需要對(duì)線程的屬性進(jìn)行配置時(shí),不會(huì)影響到Executor的內(nèi)部實(shí)現(xiàn)。

ThreadFactory主要使用的是設(shè)計(jì)模式中的工廠方法模式,可以參考設(shè)計(jì)模式的相應(yīng)章節(jié)。

Demo1-6

ThreadFactory與Executor的關(guān)系

package com.upc.upcgrid.guan.SpecialUse.chapter01;

import java.util.concurrent.Executor;

import java.util.concurrent.ThreadFactory;

public class ThreadFactoryInterface {

private static class ExecutorImp implements Executor{

private static ThreadFactory threadFactory;

@SuppressWarnings("unused")

public ExecutorImp() {

threadFactory = new ThreadFactory() {

@Override

public Thread newThread(Runnable r) {

return new Thread(r);

}

};

}

@SuppressWarnings("static-access")

public ExecutorImp(ThreadFactory tf){

this.threadFactory = tf;

}

@Override

public void execute(Runnable command) {

Thread t = threadFactory.newThread(command);

t.start();

}

}

private static class ThreadFacotoryImp implements ThreadFactory{

@Override

public Thread newThread(Runnable r) {

Thread t = new Thread(r);

t.setDaemon(false);

t.setPriority(7);

return t;

}

}

public static void main(String[] args) {

Executor executor = new ExecutorImp(new ThreadFacotoryImp());

executor.execute(new Runnable() {

@Override

public void run() {

System.out.println(Thread.currentThread());

}

});

}

}

總結(jié)

以上是生活随笔為你收集整理的java执行程序默认多线程吗_Java多线程 执行程序(1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。