欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java的多線程用法編程總結(jié)

 更新時(shí)間:2016年10月13日 11:01:07   作者:志見  
本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等。

一、進(jìn)程與線程

1、進(jìn)程是什么?

狹義定義:進(jìn)程是正在運(yùn)行的程序的實(shí)例(an instance of a computer program that is being executed)。

廣義定義:進(jìn)程是一個(gè)具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合的一次運(yùn)行活動(dòng)。它是操作系統(tǒng)動(dòng)態(tài)執(zhí)行的基本單元,在傳統(tǒng)的操作系統(tǒng)中,進(jìn)程既是基本的分配單元,也是基本的執(zhí)行單元。

2、線程是什么?

線程,有時(shí)被稱為輕量級(jí)進(jìn)程(Lightweight Process,LWP),是程序執(zhí)行流的最小單元。一個(gè)標(biāo)準(zhǔn)的線程由線程ID,當(dāng)前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進(jìn)程中的一個(gè)實(shí)體,是被系統(tǒng)獨(dú)立調(diào)度和分派的基本單位,線程自己不擁有系統(tǒng)資源,只擁有一點(diǎn)兒在運(yùn)行中必不可少的資源,但它可與同屬一個(gè)進(jìn)程的其它線程共享進(jìn)程所擁有的全部資源。

3、進(jìn)程和線程的區(qū)別?

進(jìn)程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式。

進(jìn)程有獨(dú)立的地址空間,一個(gè)進(jìn)程崩潰后,在保護(hù)模式下不會(huì)對(duì)其它進(jìn)程產(chǎn)生影響,而線程只是一個(gè)進(jìn)程中的不同執(zhí)行路徑。

線程有自己的堆棧和局部變量,但線程之間沒有單獨(dú)的地址空間,一個(gè)線程死掉就等于整個(gè)進(jìn)程死掉,所以多進(jìn)程的程序要比多線程的程序健壯,但在進(jìn)程切換時(shí),耗費(fèi)資源較大,效率要差一些。但對(duì)于一些要求同時(shí)進(jìn)行并且又要共享某些變量的并發(fā)操作,只能用線程,不能用進(jìn)程。

簡言之,線程與進(jìn)程的區(qū)別就是:

(1)一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程;
(2) 線程的劃分尺度小于進(jìn)程,使得多線程程序的并發(fā)性高。
(3)進(jìn)程在執(zhí)行過程中擁有獨(dú)立的內(nèi)存單元,而多個(gè)線程共享內(nèi)存,從而極大地提高了程序的運(yùn)行效率。
(4)線程在執(zhí)行過程中與進(jìn)程是有區(qū)別的。每個(gè)獨(dú)立的線程有一個(gè)程序運(yùn)行的入口、順序執(zhí)行序列和程序的出口。但是線程不能夠獨(dú)立執(zhí)行,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個(gè)線程執(zhí)行控制。
(5)從邏輯角度來看,多線程的意義在于一個(gè)應(yīng)用程序中,有多個(gè)執(zhí)行部分可以同時(shí)執(zhí)行。但操作系統(tǒng)并沒有將多個(gè)線程看做多個(gè)獨(dú)立的應(yīng)用,來實(shí)現(xiàn)進(jìn)程的調(diào)度和管理以及資源分配。

這就是進(jìn)程和線程的重要區(qū)別。

二、線程的生命周期及五種基本狀態(tài)

Java線程具有五種基本狀態(tài):

(1)新建狀態(tài)(New):當(dāng)線程對(duì)象對(duì)創(chuàng)建后,即進(jìn)入了新建狀態(tài),如:Thread t = new MyThread();

(2)就緒狀態(tài)(Runnable):當(dāng)調(diào)用線程對(duì)象的start()方法(t.start();),線程即進(jìn)入就緒狀態(tài)。處于就緒狀態(tài)的線程,只是說明此線程已經(jīng)做好了準(zhǔn)備,隨時(shí)等待CPU調(diào)度執(zhí)行,并不是說執(zhí)行了t.start()此線程立即就會(huì)執(zhí)行;

(3)運(yùn)行狀態(tài)(Running):當(dāng)CPU開始調(diào)度處于就緒狀態(tài)的線程時(shí),此時(shí)線程才得以真正執(zhí)行,即進(jìn)入到運(yùn)行狀態(tài)。注:就 緒狀態(tài)是進(jìn)入到運(yùn)行狀態(tài)的唯一入口,也就是說,線程要想進(jìn)入運(yùn)行狀態(tài)執(zhí)行,首先必須處于就緒狀態(tài)中;

(4)阻塞狀態(tài)(Blocked):處于運(yùn)行狀態(tài)中的線程由于某種原因,暫時(shí)放棄對(duì)CPU的使用權(quán),停止執(zhí)行,此時(shí)進(jìn)入阻塞狀態(tài),直到其進(jìn)入到就緒狀態(tài),才 有機(jī)會(huì)再次被CPU調(diào)用以進(jìn)入到運(yùn)行狀態(tài)。根據(jù)阻塞產(chǎn)生的原因不同,阻塞狀態(tài)又可以分為三種:

①等待阻塞:運(yùn)行狀態(tài)中的線程執(zhí)行wait()方法,使本線程進(jìn)入到等待阻塞狀態(tài);

②同步阻塞:線程在獲取synchronized同步鎖失敗(因?yàn)殒i被其它線程所占用),它會(huì)進(jìn)入同步阻塞狀態(tài);

③其他阻塞 : 通過調(diào)用線程的sleep()或join()或發(fā)出了I/O請(qǐng)求時(shí),線程會(huì)進(jìn)入到阻塞狀態(tài)。當(dāng)sleep()狀態(tài)超時(shí)、join()等待線程終止或者超時(shí)、或者I/O處理完畢時(shí),線程重新轉(zhuǎn)入就緒狀態(tài)。

(5)死亡狀態(tài)(Dead):線程執(zhí)行完了或者因異常退出了run()方法,該線程結(jié)束生命周期。

三、Java多線程的實(shí)現(xiàn)

在Java中,如果要實(shí)現(xiàn)多線程的程序,那么必須依靠一個(gè)線程的主體類(好比主類的概念一樣,表示一個(gè)線程的主類),但是這個(gè)線程的主體類在定義的時(shí)候需要有一些特殊的要求,這個(gè)類可以繼承Thread類或?qū)崿F(xiàn)Runnable接口來完成定義。

1、繼承Thread類實(shí)現(xiàn)多線程

java.lang.Thread是一個(gè)負(fù)責(zé)線程操作的類,任何的類繼承了Thread類就可以成為一個(gè)線程的主類。既然是主類,必須有它的使用方法,而線程啟動(dòng)的主方法需要覆寫Thread類中的run()方法才可以。

定義一個(gè)線程的主體類:

class MyThread extends Thread { // 線程的主體類
 private String title;

 public MyThread(String title) {
 this.title = title;
 }

 @Override
 public void run() { // 線程的主方法
 for (int x = 0; x < 10; x++) {
  System.out.println(this.title + "運(yùn)行,x = " + x);
 }
 }
}

現(xiàn)在已經(jīng)有了線程類,并且里面也存在了相應(yīng)的操作方法,那么就應(yīng)該產(chǎn)生對(duì)象并調(diào)用里面的方法,于是編寫出了下的程序:

public class TestDemo {
 public static void main(String[] args) {
 MyThread mt1 = new MyThread("線程A");
 MyThread mt2 = new MyThread("線程B");
 MyThread mt3 = new MyThread("線程C");
 mt1.run();
 mt2.run();
 mt3.run();
 }

 運(yùn)行結(jié)果:

線程A運(yùn)行,x = 0
線程A運(yùn)行,x = 1
線程A運(yùn)行,x = 2
線程A運(yùn)行,x = 3
線程A運(yùn)行,x = 4
線程A運(yùn)行,x = 5
線程A運(yùn)行,x = 6
線程A運(yùn)行,x = 7
線程A運(yùn)行,x = 8
線程A運(yùn)行,x = 9
線程B運(yùn)行,x = 0
線程B運(yùn)行,x = 1
線程B運(yùn)行,x = 2
線程B運(yùn)行,x = 3
線程B運(yùn)行,x = 4
線程B運(yùn)行,x = 5
線程B運(yùn)行,x = 6
線程B運(yùn)行,x = 7
線程B運(yùn)行,x = 8
線程B運(yùn)行,x = 9
線程C運(yùn)行,x = 0
線程C運(yùn)行,x = 1
線程C運(yùn)行,x = 2
線程C運(yùn)行,x = 3
線程C運(yùn)行,x = 4
線程C運(yùn)行,x = 5
線程C運(yùn)行,x = 6
線程C運(yùn)行,x = 7
線程C運(yùn)行,x = 8
線程C運(yùn)行,x = 9

我們發(fā)現(xiàn):以上的操作并沒有真正的啟動(dòng)多線程,因?yàn)槎鄠€(gè)線程彼此之間的執(zhí)行一定是交替的方式運(yùn)行,而此時(shí)是順序執(zhí)行,每一個(gè)對(duì)象的代碼執(zhí)行完之后才向下繼續(xù)執(zhí)行。

如果要想在程序之中真正的啟動(dòng)多線程,必須依靠Thread類的一個(gè)方法:public void start(),表示真正啟動(dòng)多線程,調(diào)用此方法后會(huì)間接調(diào)用run()方法:

public class TestDemo {
 public static void main(String[] args) {
 MyThread mt1 = new MyThread("線程A");
 MyThread mt2 = new MyThread("線程B");
 MyThread mt3 = new MyThread("線程C");
 mt1.start();
 mt2.start();
 mt3.start();
 }

}

 運(yùn)行結(jié)果:

線程C運(yùn)行,x = 0
線程A運(yùn)行,x = 0
線程B運(yùn)行,x = 0
線程A運(yùn)行,x = 1
線程C運(yùn)行,x = 1
線程A運(yùn)行,x = 2
線程B運(yùn)行,x = 1
線程A運(yùn)行,x = 3
線程A運(yùn)行,x = 4
線程A運(yùn)行,x = 5
線程C運(yùn)行,x = 2
線程C運(yùn)行,x = 3
線程C運(yùn)行,x = 4
線程C運(yùn)行,x = 5
線程C運(yùn)行,x = 6
線程C運(yùn)行,x = 7
線程C運(yùn)行,x = 8
線程C運(yùn)行,x = 9
線程A運(yùn)行,x = 6
線程A運(yùn)行,x = 7
線程A運(yùn)行,x = 8
線程A運(yùn)行,x = 9
線程B運(yùn)行,x = 2
線程B運(yùn)行,x = 3
線程B運(yùn)行,x = 4
線程B運(yùn)行,x = 5
線程B運(yùn)行,x = 6
線程B運(yùn)行,x = 7
線程B運(yùn)行,x = 8
線程B運(yùn)行,x = 9

此時(shí)可以發(fā)現(xiàn):多個(gè)線程之間彼此交替執(zhí)行,但每次的執(zhí)行結(jié)果是不一樣的。通過以上的代碼就可以得出結(jié)論:要想啟動(dòng)線程必須依靠Thread類的start()方法執(zhí)行,線程啟動(dòng)之后會(huì)默認(rèn)調(diào)用了run()方法。

在調(diào)用start()方法之后,發(fā)生了一系列復(fù)雜的事情:
(1)啟動(dòng)新的執(zhí)行線程(具有新的調(diào)用棧);
(2)該線程從新狀態(tài)轉(zhuǎn)移到可運(yùn)行狀態(tài);
(3)當(dāng)該線程獲得機(jī)會(huì)執(zhí)行時(shí),其目標(biāo)run()方法將運(yùn)行。
注意:對(duì)Java來說,run()方法沒有任何特別之處。像main()方法一樣,它只是新線程知道調(diào)用的方法名稱(和簽名)。因此,在Runnable上或者Thread上調(diào)用run方法是合法的,但并不啟動(dòng)新的線程。

說明:為什么線程啟動(dòng)的時(shí)候必須調(diào)用start()而不是直接調(diào)用run()?

我們發(fā)現(xiàn),在調(diào)用了start()之后,實(shí)際上它執(zhí)行的還是覆寫后的run()方法,那為什么不直接調(diào)用run()方法呢?為了解釋此問題,下面打開Thread類的源代碼,觀察一下start()方法的定義:

 public synchronized void start() {
 if (threadStatus != 0)
  throw new IllegalThreadStateException();
 group.add(this);
 boolean started = false;
 try {
  start0();
  started = true;
 } finally {
  try {
  if (!started) {
   group.threadStartFailed(this);
  }
  } catch (Throwable ignore) {
  }
 }
 }
 private native void start0();

 打開此方法的源代碼首先可以發(fā)現(xiàn):方法會(huì)拋出一個(gè)“IllegalThreadStateException”異常。一般來講,如果一個(gè)方法中使用了throw拋出一個(gè)異常對(duì)象,那么這個(gè)異常應(yīng)該使用try…catch捕獲,或者是方法的聲明上使用throws拋出,但是這塊都沒有,為什么呢?因?yàn)檫@個(gè)異常類是屬于運(yùn)行時(shí)異常(RuntimeException)的子類:

java.lang.Object
   |- java.lang.Throwable
     |- java.lang.Exception
       |- java.lang.RuntimeException
         |- java.lang.IllegalArgumentException
           |- java.lang.IllegalThreadStateException

當(dāng)一個(gè)線程對(duì)象被重復(fù)啟動(dòng)之后會(huì)拋出此異常,即:一個(gè)線程對(duì)象只能啟動(dòng)一次。

在start()方法之中有一個(gè)最為關(guān)鍵的部分就是start0()方法,而且這個(gè)方法上使用了一個(gè)native關(guān)鍵字的定義。

native關(guān)鍵字指的是Java本地接口調(diào)用(Java Native Interface),即:是使用Java調(diào)用本機(jī)操作系統(tǒng)的函數(shù)功能完成一些特殊的操作,而這樣的代碼開發(fā)在Java之中幾乎很少出現(xiàn),因?yàn)镴ava的最大特點(diǎn)是可移植性,如果一個(gè)程序只能在固定的操作系統(tǒng)上使用,那么可移植性就將徹底的喪失,所以,此操作一般不用。

多線程的實(shí)現(xiàn)一定需要操作系統(tǒng)的支持,那么以上的start0()方法實(shí)際上就和抽象方法很類似沒有方法體,而這個(gè)方法體交給JVM去實(shí)現(xiàn),即:在windows下的JVM可能使用A方法實(shí)現(xiàn)了start0(),而在Linux下的JVM可能使用了B方法實(shí)現(xiàn)了start0(),但是在調(diào)用的時(shí)候并不會(huì)去關(guān)心具體是何方式實(shí)現(xiàn)了start0()方法,只會(huì)關(guān)心最終的操作結(jié)果,交給JVM去匹配了不同的操作系統(tǒng)。

所以在多線程操作之中,使用start()方法啟動(dòng)多線程的操作是需要進(jìn)行操作系統(tǒng)函數(shù)調(diào)用的。

2、實(shí)現(xiàn)Runnable接口實(shí)現(xiàn)多線程

使用Thread類的確是可以方便的進(jìn)行多線程的實(shí)現(xiàn),但是這種方式最大的缺點(diǎn)就是單繼承的問題。為此,在java之中也可以利用Runnable接口來實(shí)現(xiàn)多線程。這個(gè)接口的定義如下:

public interface Runnable {
 public void run();
}

 通過Runnable接口實(shí)現(xiàn)多線程:

class MyThread implements Runnable { // 線程的主體類
 private String title;

 public MyThread(String title) {
 this.title = title;
 }

 @Override
 public void run() { // 線程的主方法
 for (int x = 0; x < 10; x++) {
  System.out.println(this.title + "運(yùn)行,x = " + x);
 }
 }
}

 這和之前繼承Thread類的方式區(qū)別不大,但是有一個(gè)優(yōu)點(diǎn)就是避免了單繼承局限。

不過問題來了。之前說過,如果要啟動(dòng)多線程,需要依靠Thread類的start()方法完成,之前繼承Thread類的時(shí)候可以將此方法直接繼承過來使用,但現(xiàn)在實(shí)現(xiàn)的是Runable接口,沒有這個(gè)方法可以繼承了,怎么辦?

要解決這個(gè)問題,還是需要依靠Thread類完成。在Thread類中定義了一個(gè)構(gòu)造方法,接收Runnable接口對(duì)象:

public Thread(Runnable target);

利用Thread類啟動(dòng)多線程:

public class TestDemo {
 public static void main(String[] args) throws Exception {
 MyThread mt1 = new MyThread("線程A");
 MyThread mt2 = new MyThread("線程B");
 MyThread mt3 = new MyThread("線程C");
 new Thread(mt1).start();
 new Thread(mt2).start();
 new Thread(mt3).start();
 }
}

運(yùn)行結(jié)果:

線程A運(yùn)行,x = 0
線程B運(yùn)行,x = 0
線程B運(yùn)行,x = 1
線程C運(yùn)行,x = 0
線程B運(yùn)行,x = 2
線程A運(yùn)行,x = 1
線程B運(yùn)行,x = 3
線程C運(yùn)行,x = 1
線程C運(yùn)行,x = 2
線程B運(yùn)行,x = 4
線程B運(yùn)行,x = 5
線程A運(yùn)行,x = 2
線程A運(yùn)行,x = 3
線程A運(yùn)行,x = 4
線程A運(yùn)行,x = 5
線程A運(yùn)行,x = 6
線程A運(yùn)行,x = 7
線程A運(yùn)行,x = 8
線程A運(yùn)行,x = 9
線程B運(yùn)行,x = 6
線程B運(yùn)行,x = 7
線程B運(yùn)行,x = 8
線程B運(yùn)行,x = 9
線程C運(yùn)行,x = 3
線程C運(yùn)行,x = 4
線程C運(yùn)行,x = 5
線程C運(yùn)行,x = 6
線程C運(yùn)行,x = 7
線程C運(yùn)行,x = 8
線程C運(yùn)行,x = 9

此時(shí),不但實(shí)現(xiàn)了多線程的啟動(dòng),而且沒有了單繼承局限。

3、實(shí)現(xiàn)多線程的第三種方法:.使用Callable接口實(shí)現(xiàn)多線程

使用Runnable接口實(shí)現(xiàn)的多線程可以避免單繼承局限,但是有一個(gè)問題,Runnable接口里面的run()方法不能返回操作結(jié)果。為了解決這個(gè)問題,提供了一個(gè)新的接口:Callable接口(java.util.concurrent.Callable)。

public interface Callable<V>{
 public V call() throws Exception;
}

執(zhí)行完Callable接口中的call()方法會(huì)返回一個(gè)結(jié)果,這個(gè)返回結(jié)果的類型由Callable接口上的泛型決定。

實(shí)現(xiàn)Callable接口來實(shí)現(xiàn)多線程的具體操作是:
創(chuàng)建Callable接口的實(shí)現(xiàn)類,并實(shí)現(xiàn)clall()方法;然后使用FutureTask類來包裝Callable實(shí)現(xiàn)類的對(duì)象,且以此FutureTask對(duì)象作為Thread對(duì)象的target來創(chuàng)建線程。

定義一個(gè)線程主體類:

import java.util.concurrent.Callable;

class MyThread implements Callable<String>{

 private int ticket = 10;
 @Override
 public String call() throws Exception {
 for(int i = 0 ; i < 20 ; i++){
  if(this.ticket > 0){
  System.out.println("賣票,剩余票數(shù)為"+ this.ticket --);
  }
 }
 return "票已賣光";
 }

}

Thread類沒有直接支持Callable接口。而在JDK1.5之后,提供了一個(gè)類:

java.util.concurrent.FutureTask<V>

這個(gè)類主要負(fù)責(zé)Callable接口對(duì)象操作。其定義結(jié)構(gòu)如下:

public class FutureTask<V>
extends Object
implements RunnableFurture<V>

而RunnableFurture這個(gè)接口又有如下定義:

public interface RunnableFurture<V>
extends Runnable,Future<V>

在FutureTask 類里面定義有如下構(gòu)造方法:

public FutureTask(Callable<V> callable)

現(xiàn)在,終于可以通過FutureTask類來接收Callable接口對(duì)象了,接收的目的是為了取得call()方法的返回結(jié)果。

從上面分析我們可以發(fā)現(xiàn):
FutureTask類可以接收Callable接口對(duì)象,而FutureTask類實(shí)現(xiàn)了RunnableFurture接口,RunnableFurture接口又繼承了Runnable接口。

于是,我們可以這樣來啟動(dòng)多線程:

public class TestDemo {
 public static void main(String[] args) throws Exception {
 MyThread mt1 = new MyThread();
 MyThread mt2 = new MyThread();

 FutureTask<String> task1 = new FutureTask<String>(mt1);//取得call()方法返回結(jié)果
 FutureTask<String> task2 = new FutureTask<String>(mt2);//取得call()方法返回結(jié)果

 //FutureTask是Runnable接口的子類,可以使用Thread類的構(gòu)造來接收task對(duì)象
 new Thread(task1).start();
 new Thread(task2).start();

 //多線程執(zhí)行完畢后,可以使用FutureTask的父接口Future中的get()方法取得執(zhí)行結(jié)果
 System.out.println("線程1的返回結(jié)果:"+task1.get());
 System.out.println("線程2的返回結(jié)果:"+task2.get());
 }
}

運(yùn)行結(jié)果:

賣票,剩余票數(shù)為10
賣票,剩余票數(shù)為10
賣票,剩余票數(shù)為9
賣票,剩余票數(shù)為8
賣票,剩余票數(shù)為7
賣票,剩余票數(shù)為9
賣票,剩余票數(shù)為6
賣票,剩余票數(shù)為8
賣票,剩余票數(shù)為5
賣票,剩余票數(shù)為7
賣票,剩余票數(shù)為4
賣票,剩余票數(shù)為6
賣票,剩余票數(shù)為3
賣票,剩余票數(shù)為5
賣票,剩余票數(shù)為2
賣票,剩余票數(shù)為4
賣票,剩余票數(shù)為1
賣票,剩余票數(shù)為3
賣票,剩余票數(shù)為2
賣票,剩余票數(shù)為1
線程1的返回結(jié)果:票已賣光
線程2的返回結(jié)果:票已賣光

小結(jié):

上述講解了三種實(shí)現(xiàn)多線程的方式,對(duì)于線程的啟動(dòng)而言,都是調(diào)用線程對(duì)象的start()方法,需要特別注意的是:不能對(duì)同一線程對(duì)象兩次調(diào)用start()方法。

相關(guān)文章

  • Java8 HashMap鍵與Comparable接口小結(jié)

    Java8 HashMap鍵與Comparable接口小結(jié)

    這篇文章主要介紹了Java8 HashMap鍵與Comparable接口小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • maven如何打包動(dòng)態(tài)環(huán)境變量(包括啟動(dòng)腳本)

    maven如何打包動(dòng)態(tài)環(huán)境變量(包括啟動(dòng)腳本)

    這篇文章主要介紹了maven如何打包動(dòng)態(tài)環(huán)境變量(包括啟動(dòng)腳本)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • springboot啟動(dòng)時(shí)如何獲取端口和項(xiàng)目名

    springboot啟動(dòng)時(shí)如何獲取端口和項(xiàng)目名

    這篇文章主要介紹了springboot啟動(dòng)時(shí)如何獲取端口和項(xiàng)目名,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 詳解MyBatis配置typeAliases的方法

    詳解MyBatis配置typeAliases的方法

    這篇文章主要介紹了詳解MyBatis配置typeAliases的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Windows中Tomcat整合到Eclipse的圖文教程

    Windows中Tomcat整合到Eclipse的圖文教程

    下面小編就為大家?guī)硪黄猈indows中Tomcat整合到Eclipse的圖文教程。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • java簡單列出文件夾下所有文件的方法

    java簡單列出文件夾下所有文件的方法

    這篇文章主要介紹了java簡單列出文件夾下所有文件的方法,涉及java針對(duì)文件夾遍歷操作相關(guān)技巧,需要的朋友可以參考下
    2016-08-08
  • Idea如何自定義VM配置

    Idea如何自定義VM配置

    這篇文章主要介紹了Idea如何自定義VM配置,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Java中各種集合判空方法總結(jié)

    Java中各種集合判空方法總結(jié)

    最近接觸集合比較多,經(jīng)常對(duì)于集合是否為空做判斷,下面這篇文章主要給大家介紹了關(guān)于Java中各種集合判空方法總結(jié)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • Java詳解使用線程池處理任務(wù)方法

    Java詳解使用線程池處理任務(wù)方法

    java中經(jīng)常需要用到多線程來處理,我們非常不建議單純使用繼承Thread或者實(shí)現(xiàn)Runnable接口的方式來創(chuàng)建線程,那樣勢(shì)必有創(chuàng)建及銷毀線程耗費(fèi)資源、線程上下文切換問題。同時(shí)創(chuàng)建過多的線程也可能引發(fā)資源耗盡的風(fēng)險(xiǎn),這個(gè)時(shí)候引入線程池比較合理,方便線程任務(wù)的管理
    2022-05-05
  • Java使用application.property讀取文件里面的值

    Java使用application.property讀取文件里面的值

    本文通過實(shí)例代碼給大家介紹了Java使用application.property讀取文件里面的值,需要的朋友可以參考下
    2018-10-10

最新評(píng)論