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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

java

java ee13_一口气了解多线程及其Java实现

發(fā)布時(shí)間:2023/12/2 java 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java ee13_一口气了解多线程及其Java实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

進(jìn)程:進(jìn)程就是應(yīng)用程序在內(nèi)存中分配的空間,也就是正在運(yùn)行的程序,各個(gè)進(jìn)程之間不干擾。同時(shí)進(jìn)程保存著程序每一個(gè)時(shí)刻運(yùn)行的狀態(tài)。

程序:用某種編程語(yǔ)言(java、python等)編寫(xiě),能夠完成一定任務(wù)或者功能的代碼集合,是指令和數(shù)據(jù)的有序集合,是一段靜態(tài)代碼。

線程:通常一個(gè)進(jìn)程中可以包含若干個(gè)線程。進(jìn)程單獨(dú)占有一定的內(nèi)存地址空間,而線程共享所屬進(jìn)程占有的內(nèi)存地址空間和資源。

在Java中,我們是如何使用多線程的呢?

1.使用Thread 類和 Runnalble 接?來(lái)實(shí)現(xiàn)自己的“線程”類。

// 繼承Thread類

public class MyThread1 extends Thread {

@Override

public void run() {

System.out.println("MyThread1*********");

}

}

// 實(shí)現(xiàn)Runnable接口

public class MyThread2 implements Runnable {

@Override

public void run() {

System.out.println("MyThread2@@@@@@@@@");

}

}

public class ThreadTest {

public static void main(String[] args) {

Thread myThread1 = new MyThread1();

myThread1.start();

Thread myThread2 = new Thread(new MyThread2());

myThread2.start();

new Thread(new Runnable() {

@Override

public void run() {

System.out.println("MyThread3########");

}

}).start();

new Thread(() -> {

System.out.println("MyThread4%%%%%%%%");

}).start();

}

}

2.我們使用Runnable和Thread來(lái)創(chuàng)建一個(gè)新的線程。但是他們有一個(gè)弊端,就是run方法是沒(méi)有返回值的。而有時(shí)候我們希望開(kāi)啟一個(gè)線程去執(zhí)行一個(gè)任務(wù),并且這個(gè)任務(wù)執(zhí)行完成之后有一個(gè)返回值。JDK提供了Callable接口和Future類為我們解決了這個(gè)問(wèn)題。

public class CallableTask implements Callable {

@Override

public String call() throws Exception {

Thread.sleep(1000);

return "中獎(jiǎng)啦~";

}

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

// 1.使用Future接口

// ExecutorService可以使用submit方法來(lái)讓?個(gè)Callable接口執(zhí)行。

ExecutorService executor1 = Executors.newCachedThreadPool();

CallableTask task = new CallableTask();

Future result = executor1.submit(task);

// 注意調(diào)用get方法會(huì)阻塞當(dāng)前線程,直到得到結(jié)果。

// 所以實(shí)際編碼中建議使用可以設(shè)置超時(shí)時(shí)間的重載get方法。

System.out.println(result.get() + "@@");

// 2.使用FutureTask類:FutureTask 是實(shí)現(xiàn)的 RunnableFuture 接口的,

// 而 RunnableFuture 接口同時(shí)繼承了 Runnable 接口和 Future 接口。

ExecutorService executor2 = Executors.newCachedThreadPool();

FutureTask futureTask = new FutureTask<>(new CallableTask());

executor2.submit(futureTask);

System.out.println(futureTask.get() + "**");

}

}

什么是線程組和線程優(yōu)先級(jí)?

1.線程組:每個(gè)Thread必然存在于?個(gè)ThreadGroup中,Thread不能獨(dú)?于ThreadGroup存在。執(zhí)?main()?法線程的名字是main,如果在new Thread時(shí)沒(méi)有顯式指定,那么默認(rèn)將?線程(當(dāng)前執(zhí)?new Thread的線程)線程組設(shè)置為??的線程組。

public class ThreadGroupTest {

public static void main(String[] args) {

Thread testThread1 = new Thread(() -> {

System.out.println("testThread1當(dāng)前線程組名字:" +

Thread.currentThread().getThreadGroup().getName());

System.out.println("testThread1線程名字:" +

Thread.currentThread().getName());

});

Thread testThread2 = new Thread(() -> {

System.out.println("testThread2當(dāng)前線程組名字:" +

Thread.currentThread().getThreadGroup().getName());

System.out.println("testThread2線程名字:" +

Thread.currentThread().getName());

});

testThread1.start();

testThread2.start();

System.out.println("執(zhí)?main?法線程名字:" + Thread.currentThread().getName());

}

}

輸出結(jié)果:

執(zhí)?main?法線程名字:main

testThread2當(dāng)前線程組名字:main

testThread2線程名字:Thread-1

testThread1當(dāng)前線程組名字:main

testThread1線程名字:Thread-0

2.線程優(yōu)先級(jí):Java中線程優(yōu)先級(jí)可以指定,范圍是1~10 。但并不是所有的操作系統(tǒng)都支持10級(jí)優(yōu)先級(jí)的劃分,Java只是給操作系統(tǒng)一個(gè)優(yōu)先級(jí)的參考值,線程最終在操作系統(tǒng)的優(yōu)先級(jí)是多少還是由操作系統(tǒng)決定。通常情況下,?優(yōu)先級(jí)的線程將會(huì)?低優(yōu)先級(jí)的線程有更?的?率得到執(zhí)?。

public static void main(String[] args) {

Thread a = new Thread();

System.out.println("我是默認(rèn)線程優(yōu)先級(jí):"+a.getPriority());

Thread b = new Thread();

b.setPriority(10);

System.out.println("我是設(shè)置過(guò)的線程優(yōu)先級(jí):"+b.getPriority());

}

我是默認(rèn)線程優(yōu)先級(jí):5

我是設(shè)置過(guò)的線程優(yōu)先級(jí):10

線程狀態(tài)

線程狀態(tài)轉(zhuǎn)換圖

鎖與同步

無(wú)鎖的時(shí)候,如下代碼中兩個(gè)線程A、B各自執(zhí)行:

public class ThreadNoneLock {

static class ThreadA implements Runnable {

@Override

public void run() {

for (int i = 0; i < 100; i++) {

System.out.println("Thread A " + i);

}

}

}

static class ThreadB implements Runnable {

@Override

public void run() {

for (int i = 0; i < 100; i++) {

System.out.println("Thread B " + i);

}

}

}

public static void main(String[] args) {

new Thread(new ThreadA()).start();

new Thread(new ThreadB()).start();

}

}

Thread A 0

Thread A 1

Thread A 2

Thread B 0

Thread B 1

Thread B 2

Thread B 3

...

Thread B 97

Thread B 98

Thread B 99

Thread A 3

Thread A 4

Thread A 5

加鎖之后(用synchronized關(guān)鍵字加上了同一個(gè)對(duì)象鎖lock),A線程先執(zhí)行完,B隨后執(zhí)行:

public class ThreadWithLock {

private static Object lock = new Object();

static class ThreadA implements Runnable {

@Override

public void run() {

synchronized (lock) {

for (int i = 0; i < 100; i++) {

System.out.println("Thread A " + i);

}

}

}

}

static class ThreadB implements Runnable {

@Override

public void run() {

synchronized (lock) {

for (int i = 0; i < 100; i++) {

System.out.println("Thread B " + i);

}

}

}

}

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

new Thread(new ThreadA()).start();

Thread.sleep(10);

new Thread(new ThreadB()).start();

}

}

Thread A 97

Thread A 98

Thread A 99

Thread B 0

Thread B 1

Thread B 2

等待/通知機(jī)制

如下例子中,線程A和線程B首先打印出自己需要的東西,然后使用notify()方法叫醒另一個(gè)正在等待的線程,然后自己使用wait()方法陷入等待并釋放lock鎖。

public class WaitAndNotify {

private static Object lock = new Object();

static class ThreadA implements Runnable {

@Override

public void run() {

synchronized (lock) {

for (int i = 0; i < 5; i++) {

try {

System.out.println("Thread A: " + i);

lock.notify();

lock.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

lock.notify();

}

}

}

static class ThreadB implements Runnable {

@Override

public void run() {

synchronized (lock) {

for (int i = 0; i < 5; i++) {

try {

System.out.println("Thread B: " + i);

lock.notify();

lock.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

lock.notify();

}

}

}

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

new Thread(new ThreadA()).start();

Thread.sleep(1000);

new Thread(new ThreadB()).start();

}

}

Thread A: 0

Thread B: 0

Thread A: 1

Thread B: 1

Thread A: 2

Thread B: 2

Thread A: 3

Thread B: 3

Thread A: 4

Thread B: 4

信號(hào)量

public class Signal {

/**

* volatile關(guān)鍵字可以保證內(nèi)存的可見(jiàn)性,如果用volatile關(guān)鍵字聲明了一個(gè)變量,在一個(gè)線程里改變了這個(gè)變量值,那其他線程是立馬可見(jiàn)更改后的值的。

*/

private static volatile int i = 0;

static class ThreadA implements Runnable {

@Override

public void run() {

while (i < 10) {

if (i % 2 == 0) {

System.out.println("Thread A: "+ i);

synchronized (this) {

i++;

}

}

}

}

}

static class ThreadB implements Runnable {

@Override

public void run() {

while (i < 10) {

if (i % 2 == 1) {

System.out.println("Thread B: " + i);

synchronized (this) {

i++;

}

}

}

}

}

public static void main(String[] args) {

new Thread(new ThreadA()).start();

new Thread(new ThreadB()).start();

}

}

Thread A: 0

Thread B: 1

Thread A: 2

Thread B: 3

Thread A: 4

Thread B: 5

Thread A: 6

Thread B: 7

Thread A: 8

Thread B: 9

ThreadLocal

多線程訪問(wèn)同一個(gè)共享變量的時(shí)候容易出現(xiàn)并發(fā)問(wèn)題,特別是多個(gè)線程對(duì)同一個(gè)變量進(jìn)行寫(xiě)入的時(shí)候,為了保證線程安全,一般使用者在訪問(wèn)共享變量的時(shí)候需要進(jìn)行額外的同步措施才能保證線程安全性。TreadLocal是除了加鎖這種同步方式之外的一種保證規(guī)避多線程訪問(wèn)出現(xiàn)線程不安全的方法,當(dāng)我們?cè)趧?chuàng)建一個(gè)變量后,如果每個(gè)線程對(duì)其進(jìn)行訪問(wèn)的時(shí)候訪問(wèn)的都是線程自己的變量這樣就不會(huì)存在線程不安全的問(wèn)題了。

線程池

為什么要使用線程池:1.創(chuàng)建/銷(xiāo)毀線程需要消耗系統(tǒng)資源,線程池可以復(fù)用已創(chuàng)建的線程。2.控制并發(fā)的數(shù)量。并發(fā)數(shù)量過(guò)多,可能會(huì)導(dǎo)致資源消耗過(guò)多,從而造成服務(wù)器崩潰。3.可以對(duì)線程做統(tǒng)一管理。

ThreadPoolExecutor

public class ThreadPoolExecutorTest {

public static void main(String[] args) {

// ThreadPoolExecutor提供了四個(gè)構(gòu)造函數(shù): 1至5; 1至5 + 6; 1至5 + 7; 1至5 + 6 + 7

// 參數(shù)一:int corePoolSize 該線程池中核心線程數(shù)最大值,線程池新建的時(shí)候,如果當(dāng)前線程總數(shù)小于corePoolSize,則新建核心線程,如果超過(guò)corePoolSize,則新建的是非核心線程

// 參數(shù)二:int maximumPoolSize 該線程池中線程總數(shù)最大值

// 參數(shù)三:long keepAliveTime 該線程池中非核心線程閑置超時(shí)時(shí)長(zhǎng)

// 參數(shù)四:TimeUnit unit keepAliveTime的單位

// 參數(shù)五:BlockingQueue workQueue 該線程池中的任務(wù)隊(duì)列,維護(hù)著等待執(zhí)行的Runnable對(duì)象。常見(jiàn)類型:

// SynchronousQueue:這個(gè)隊(duì)列接收到任務(wù)的時(shí)候,會(huì)直接提交給線程處理,而不保留它,如果所有線程都在工作怎么辦?那就新建一個(gè)線程來(lái)處理這個(gè)任務(wù)!所以為了保證不出現(xiàn)的錯(cuò)誤,使用這個(gè)類型隊(duì)列的時(shí)候,maximumPoolSize一般指定成Integer.MAX_VALUE,即無(wú)限大

// LinkedBlockingQueue:這個(gè)隊(duì)列接收到任務(wù)的時(shí)候,如果當(dāng)前線程數(shù)小于核心線程數(shù),則新建線程(核心線程)處理任務(wù);如果當(dāng)前線程數(shù)等于核心線程數(shù),則進(jìn)入隊(duì)列等待。由于這個(gè)隊(duì)列沒(méi)有最大值限制,即所有超過(guò)核心線程數(shù)的任務(wù)都將被添加到隊(duì)列中,這也就導(dǎo)致了maximumPoolSize的設(shè)定失效,因?yàn)榭偩€程數(shù)永遠(yuǎn)不會(huì)超過(guò)corePoolSize

// ArrayBlockingQueue:可以限定隊(duì)列的長(zhǎng)度,接收到任務(wù)的時(shí)候,如果沒(méi)有達(dá)到corePoolSize的值,則新建線程(核心線程)執(zhí)行任務(wù),如果達(dá)到了,則入隊(duì)等候,如果隊(duì)列已滿,則新建線程(非核心線程)執(zhí)行任務(wù),又如果總線程數(shù)到了maximumPoolSize,并且隊(duì)列也滿了,則發(fā)生錯(cuò)誤

// DelayQueue:隊(duì)列內(nèi)元素必須實(shí)現(xiàn)Delayed接口,這就意味著你傳進(jìn)去的任務(wù)必須先實(shí)現(xiàn)Delayed接口。這個(gè)隊(duì)列接收到任務(wù)時(shí),首先先入隊(duì),只有達(dá)到了指定的延時(shí)時(shí)間,才會(huì)執(zhí)行任務(wù)

// 參數(shù)六:ThreadFactory threadFactory 給線程起名字

// 參數(shù)七:RejectedExecutionHandler handler 異常處理

ThreadFactory threadFactory = new ThreadFactory() {

@Override

public Thread newThread(Runnable r) {

return new Thread(r,"thread name...");

}

};

// lambda表達(dá)式寫(xiě)法

// ThreadFactory threadFactory = (Runnable r) -> new Thread(r,"thread name");

ThreadPoolExecutor executor = new ThreadPoolExecutor(5,5,0L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(), threadFactory, new ThreadPoolExecutor.AbortPolicy());

executor.execute(new Runnable() {

@Override

public void run() {

System.out.println("@@@@");

}

});

}

}

總結(jié)

以上是生活随笔為你收集整理的java ee13_一口气了解多线程及其Java实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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