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

java實(shí)現(xiàn)/創(chuàng)建線(xiàn)程的幾種方式小結(jié)

 更新時(shí)間:2021年08月09日 09:11:36   作者:勇敢牛牛不怕困難@帥  
在JAVA中,用Thread類(lèi)代表線(xiàn)程,所有線(xiàn)程對(duì)象都必須是Thread類(lèi)或者Thread類(lèi)子類(lèi)的實(shí)例,下面這篇文章主要介紹了java實(shí)現(xiàn)/創(chuàng)建線(xiàn)程的幾種方式,需要的朋友可以參考下

進(jìn)程與線(xiàn)程

進(jìn)程可以簡(jiǎn)單理解成一個(gè)可執(zhí)行程序例如.exe,在Windows中的任務(wù)管理器中可以查看每一個(gè)進(jìn)程,進(jìn)程是一次程序的執(zhí)行,是程序在數(shù)據(jù)集合上運(yùn)行的過(guò)程,是系統(tǒng)資源調(diào)度的一個(gè)單位。進(jìn)程主要負(fù)責(zé)向操作系統(tǒng)申請(qǐng)資源。然而一個(gè)進(jìn)程中,多個(gè)線(xiàn)程可以共享進(jìn)程中相同的內(nèi)存或文件資源。線(xiàn)程就是一個(gè)進(jìn)程一個(gè)程序要完成所依賴(lài)的子任務(wù),這些子任務(wù)便可以看作是一個(gè)線(xiàn)程。

第一種方式繼承Thread類(lèi)

從java源碼可以看出Thread類(lèi)本質(zhì)上實(shí)現(xiàn)了Runnable接口的實(shí)例類(lèi),代表了線(xiàn)程的一個(gè)線(xiàn)程的實(shí)例,啟動(dòng)的線(xiàn)程唯一辦法就是通過(guò)Thread類(lèi)調(diào)用start()方法,start()方法是需要本地操作系統(tǒng)的支持,它將啟動(dòng)一個(gè)新的線(xiàn)程,并且執(zhí)行run()方法。

繼承Thread類(lèi)實(shí)現(xiàn)線(xiàn)程代碼如下

創(chuàng)建一個(gè)Thread類(lèi),對(duì)象直接調(diào)用run方法會(huì)出現(xiàn)什么問(wèn)題?

package cn.thread.線(xiàn)程;

public class MyThread extends Thread{
    public MyThread(String name){
        super(null,null,name);
    }
    int piao =10;
    @Override
    public void run() {
        while(piao>0){
            System.out.println(Thread.currentThread().getName()+"......"+piao--);
        }
    }

    public static void main(String[] args) {
        MyThread mt = new MyThread("x");
        mt.run();
    }
}

結(jié)果:

可以發(fā)現(xiàn)是主線(xiàn)程執(zhí)行了run方法,并不是用戶(hù)線(xiàn)程執(zhí)行的run方法,此時(shí)可以得出用戶(hù)線(xiàn)程并沒(méi)有啟動(dòng),所以并不會(huì)執(zhí)行run里面的方法,且執(zhí)行完run方法便結(jié)束線(xiàn)程。

第二種創(chuàng)建線(xiàn)程的方法,實(shí)現(xiàn)Runnable接口

相比繼承Thread類(lèi)而言,實(shí)現(xiàn)接口的可擴(kuò)展性得到了提升,Runnable接口也必須要封裝到Thread類(lèi)里面,才可以調(diào)用start方法,啟動(dòng)線(xiàn)程。

實(shí)現(xiàn)代碼

package cn.thread.線(xiàn)程;

public class MyRunnable implements Runnable{

    int piao = 10;
    @Override
    public void run() {
        while(piao>0){
            System.out.println(Thread.currentThread().getName()+"-----"+piao--);
        }
    }

    public static void main(String[] args) {
        Runnable r =new MyRunnable();
        Thread t =new Thread(r);
        t.start();
    }

}

結(jié)果

第三種創(chuàng)建線(xiàn)程的方法實(shí)現(xiàn)Callable接口

Callable接口使用方法和Runnable接口的方法類(lèi)似不同的一點(diǎn)是Callable接口具有返回值,返回結(jié)果并且可能拋出異常的任務(wù)。實(shí)現(xiàn)者定義了一個(gè)不帶任何參數(shù)的叫做 call 的方法。 Callable 接口類(lèi)似于 Runnable,兩者都是為那些其實(shí)例可能被另一個(gè)線(xiàn)程執(zhí)行的類(lèi)設(shè)計(jì)的。但是 Runnable 不會(huì)返回結(jié)果,并且無(wú)法拋出經(jīng)過(guò)檢查的異常。

實(shí)現(xiàn)代碼

對(duì)下列代碼進(jìn)行分析

首先callable是接口不能直接創(chuàng)建對(duì)象,也不能創(chuàng)建線(xiàn)程。并且要實(shí)現(xiàn)call方法類(lèi)似run方法的功能,call方法有返回值,會(huì)計(jì)算結(jié)果,如果無(wú)法計(jì)算結(jié)果,則拋出一個(gè)異常。

執(zhí)行callable任務(wù)之后,可以獲得一個(gè)future的對(duì)象,future基本上是主線(xiàn)程可以跟蹤進(jìn)度以及獲取其他線(xiàn)程結(jié)果的一種方式。在這里Test1()方法主要利用線(xiàn)程池和future的方法,去啟動(dòng)實(shí)現(xiàn)Callable接口的線(xiàn)程,具有返回值。而Test2()主要是采用FutureTask類(lèi)去實(shí)現(xiàn)創(chuàng)建一個(gè)實(shí)現(xiàn)callable接口的線(xiàn)程,futuretask實(shí)現(xiàn)了future接口。

package com.openlab.test;

import java.util.Random;
import java.util.concurrent.Callable;

public class CallableTest implements Callable{

	@Override
	public Object call() throws Exception {
		
		Random generator = new Random();
		
		Integer randomNumber = generator.nextInt(5);
		
		Thread.sleep(randomNumber*1000);
		
		return randomNumber;
	}

}

綜合練習(xí)代碼:

package cn.thread.線(xiàn)程;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

public class CallableTest implements Callable<Object> {//不能直接創(chuàng)建線(xiàn)程
    int taskNum;
    public CallableTest(int taskNum){
        this.taskNum = taskNum;

    }
    @Override
    public Object call() throws Exception {

        System.out.println(">>>"+taskNum+"任務(wù)啟動(dòng)");
        Date dataTemp = new Date();
        Thread.sleep(1000);
        Date dataTemp2 = new Date();
        long time  = dataTemp2.getTime() - dataTemp.getTime();
        System.out.println(">>>>"+taskNum+"任務(wù)終止");
        return taskNum+"任務(wù)返回運(yùn)行結(jié)果"+time;
//        Random generator = new Random();
//        Integer randomNumber = generator.nextInt(5);
//        Thread.sleep(randomNumber*1000);
//        return  randomNumber;
    }
    /*test1方法采用Executors的靜態(tài)方法newFixedThreadPool(taskSize) 創(chuàng)建一個(gè)可重用固定線(xiàn)程集合的
    線(xiàn)程池,以共享的無(wú)界隊(duì)列方式來(lái)運(yùn)行這些線(xiàn)程,獲取線(xiàn)程池。ExecutorService的submit方法提交一個(gè)
    callable實(shí)例,得到一個(gè)future對(duì)象,最終將future對(duì)象存儲(chǔ)在list數(shù)組中,加入線(xiàn)程池的過(guò)程中就代表
    著線(xiàn)程已經(jīng)開(kāi)始執(zhí)行,相當(dāng)于一個(gè)線(xiàn)程池代理過(guò)程,就不需要采用start方法啟動(dòng)線(xiàn)程。最后對(duì)future進(jìn)行
    打印輸出。切記一定要關(guān)閉線(xiàn)程池!*/
     static void test1() throws ExecutionException, InterruptedException {
         System.out.println("程序開(kāi)始");
         Date data1 = new Date();
         int taskSize = 5;
        //構(gòu)建線(xiàn)程池對(duì)象
         ExecutorService pool = Executors.newFixedThreadPool(taskSize);
         List<Future> list =new ArrayList<Future>();
         for(int i=0;i<taskSize;i++){

             Callable c = new CallableTest(i);
             Future f = pool.submit(c);
             list.add(pool.submit(c));

         }
         //關(guān)閉線(xiàn)程池
         pool.shutdown();
         for(Future f:list){
             System.out.println(">>>"+f.get().toString());
         }
         Date date2 = new Date();
         System.out.println("程序運(yùn)行結(jié)束-----"+(date2.getTime()-data1.getTime())+"毫秒");
     }
     /*test2方法主要是采用futuretask類(lèi),可以直接把callable作為參數(shù)來(lái)申明futuretask對(duì)象,
     這里相當(dāng)于把線(xiàn)程池?fù)Q成了futuretask數(shù)組,因?yàn)閠est1線(xiàn)程池可以對(duì)callable進(jìn)行封裝,
     在這里可以直接采用futuretask就行封裝,在加上futuretask又實(shí)現(xiàn)了runnable接口,
     所以可以直接創(chuàng)建線(xiàn)程采用start的方式進(jìn)行啟動(dòng)線(xiàn)程。*/
     static  void test2() throws ExecutionException, InterruptedException {
         System.out.println("----程序開(kāi)始-----");
         Date date1 =new Date();
         int taskSize = 5;
         FutureTask[] randNumber = new FutureTask[taskSize];
         List<Future> list =new ArrayList<Future>();
         for(int i=0;i<taskSize;i++){
             Callable c = new CallableTest(i);
             randNumber[i] = new FutureTask(c);
             Thread t = new Thread(randNumber[i]);
             t.start();

         }
         for(Future f:randNumber){
             System.out.println(">>>"+f.get().toString());
         }
         Date date2 = new Date();
         System.out.println("程序運(yùn)行結(jié)束-----"+(date2.getTime()-date1.getTime())+"毫秒");

     }
    public static void main(String[] args) throws Exception {
//        CallableTest c = new CallableTest();
//        Integer i = (Integer) c.call();
        test1();
        test2();

    }
}

執(zhí)行結(jié)果

第四種實(shí)現(xiàn)線(xiàn)程的方法,基于線(xiàn)程池

其實(shí)在第三種的方法中就提到了兩種實(shí)現(xiàn)方法,一種線(xiàn)程池+future,另一種futuretask的方法。線(xiàn)程和數(shù)據(jù)庫(kù)連接這些資源都是非常寶貴的資源。那么每次需要的時(shí)候創(chuàng)建,不需要的時(shí)候銷(xiāo)毀,是非常浪費(fèi)資源的。那么我們就可以使用緩存的策略,也就是使用線(xiàn)程池。

// 創(chuàng)建線(xiàn)程池
 ExecutorService threadPool = Executors.newFixedThreadPool(10);
 while(true) {
 threadPool.execute(new Runnable() { // 提交多個(gè)線(xiàn)程任務(wù),并執(zhí)行
 @Override
 public void run() {
 System.out.println(Thread.currentThread().getName() + " is running ..");
 try {
 Thread.sleep(3000);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }
 });
 } }

總結(jié)

理論上實(shí)現(xiàn)線(xiàn)程的方法還有一些,本文所提及到的,基本都是一些創(chuàng)建線(xiàn)程常用的方法。希望本文對(duì)大家在學(xué)習(xí)線(xiàn)程的過(guò)程中有所幫助。

相關(guān)文章

  • Java中this關(guān)鍵字的用法詳解

    Java中this關(guān)鍵字的用法詳解

    我知道很多朋友都和我一樣,在JAVA程序中似乎經(jīng)常見(jiàn)到this,自己也偶爾用到它,但是到底this該怎么用,卻心中無(wú)數(shù),下面這篇文章主要給大家介紹了關(guān)于Java中this關(guān)鍵字用法的相關(guān)資料,需要的朋友可以參考下
    2023-05-05
  • Java以編程方式實(shí)現(xiàn)JAR文件的創(chuàng)建

    Java以編程方式實(shí)現(xiàn)JAR文件的創(chuàng)建

    在這篇文章中,我們將為大家詳細(xì)介紹一下利用Java語(yǔ)言以編程方式創(chuàng)建jar文件的過(guò)程。文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2022-07-07
  • Java面試題沖刺第九天--MyBatis

    Java面試題沖刺第九天--MyBatis

    這篇文章主要為大家分享了最有價(jià)值的三道MyBatis框架面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-07-07
  • SpringBoot集成MQTT示例詳解

    SpringBoot集成MQTT示例詳解

    這篇文章主要為大家介紹了SpringBoot集成MQTT示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • 使用HttpSessionListener監(jiān)聽(tīng)器實(shí)戰(zhàn)

    使用HttpSessionListener監(jiān)聽(tīng)器實(shí)戰(zhàn)

    這篇文章主要介紹了使用HttpSessionListener監(jiān)聽(tīng)器實(shí)戰(zhàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java語(yǔ)言獲取TCP流的實(shí)現(xiàn)步驟

    Java語(yǔ)言獲取TCP流的實(shí)現(xiàn)步驟

    使用Wireshark分析網(wǎng)絡(luò)包時(shí),一個(gè)很常用的功能就是選中一個(gè)TCP報(bào)文,然后查看這個(gè)TCP報(bào)文的TCP流,從而可以進(jìn)一步分析建連是否慢了,斷連是否正常等情況,那么本文就TCP流的概念以及在Java中如何獲取,做一個(gè)簡(jiǎn)單的學(xué)習(xí),需要的朋友可以參考下
    2023-11-11
  • 使用logstash同步mysql數(shù)據(jù)到elasticsearch實(shí)現(xiàn)

    使用logstash同步mysql數(shù)據(jù)到elasticsearch實(shí)現(xiàn)

    這篇文章主要為大家介紹了使用logstash同步mysql數(shù)據(jù)到elasticsearch實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 如何解決使用restTemplate進(jìn)行feign調(diào)用new HttpEntity<>報(bào)錯(cuò)問(wèn)題

    如何解決使用restTemplate進(jìn)行feign調(diào)用new HttpEntity<>報(bào)錯(cuò)問(wèn)題

    這篇文章主要介紹了如何解決使用restTemplate進(jìn)行feign調(diào)用new HttpEntity<>報(bào)錯(cuò)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • Java groovy如何提升代碼運(yùn)行效率

    Java groovy如何提升代碼運(yùn)行效率

    這篇文章主要介紹了Java groovy如何提升代碼運(yùn)行效率,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • SpringBoot外部化配置示例解析

    SpringBoot外部化配置示例解析

    這篇文章主要介紹了SpringBoot外部化配置示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02

最新評(píng)論