Heim  >  Artikel  >  Java  >  Wie erstelle und führe ich Threads in Java aus?

Wie erstelle und führe ich Threads in Java aus?

王林
王林nach vorne
2023-04-19 14:16:051588Durchsuche

    1. Fünf Möglichkeiten, Threads zu erstellen und auszuführen

    Die erste: die Thread-Klasse erben

    # 🎜🎜#Diese Methode ist die grundlegendste Methode. Freunde, die Java studiert haben, wissen sie alle, daher werde ich nicht auf Details eingehen. Es ist zu beachten, dass:

    Die Override-Implementierung verwendet die Ausführungsmethode und der laufende Thread verwendet die Startmethode.

    public class FirstWay extends Thread  {
        @Override
        public void run() {
            System.out.println("第一种实现线程的方式:继承Thread类");
        }
        //模拟测试
        public static void main(String[] args) {
            new FirstWay().start();
        }
    }

    Zweitens: Implementieren Sie die Runnable-Schnittstelle

    Die zweite Implementierungsmethode ist immer noch sehr einfach: Erben Sie die Runnable-Schnittstelle und schreiben Sie die Ausführungsmethode neu, um die Thread-Lauflogik zu implementieren . Hinweis: Der laufende Thread erfordert eine Ebene von neuer Thread.

    public class SecondWay implements Runnable{
        @Override
        public void run() {
            System.out.println("第二种实现线程的方式:实现Runnable接口");
        }
        //模拟测试
        public static void main(String[] args) {
            new Thread(new SecondWay()).start();
        }
    }
    new Thread 。

    public class ThirdWay implements Callable<String> {
        @Override
        public String call() throws Exception {
            System.out.println("第三种实现线程的方式:实现Callable接口");
            return "Callable接口带返回值,可以抛出异常";
        }
    
        //模拟测试
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            FutureTask<String> futureTask = new FutureTask<>(new ThirdWay());
            new Thread(futureTask).start();
            //阻塞方法,获取call方法返回值
            System.out.println(futureTask.get());  //打印:Callable接口带返回值,可以抛出异常
        }
    }

    第三种:实现Callable接口

    第三种方式是实现Callable接口,Callable接口与Runable接口都能实现线程。

    public class FourthWay implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() +
                    ":实现线程的方式Runnable接口,但运行方式不一样,使用线程池");
        }
    
        public static void main(String[] args) {
            //创建一个固定大小的线程池
            ExecutorService threadPool = Executors.newFixedThreadPool(5);
            for(int i = 0;i < 10;i++){
                threadPool.execute(new FourthWay());
            }
        }
    }

    区别如下:

    • Callable接口实现线程方法是call, Runable接口实现线程方法是run

    • Callable有返回值, Runable接口不能有返回值

    • Callable接口方法call返回值可以设置泛型,如下例子中使用String数据类型

    • Callable接口方法call方法可以抛出异常,Runable接口run方法不可以抛出异常

    • Callable接口方法通过new Thread(futureTask).start()运行,FutureTask的get方法可以获取Callable接口方法call方法的返回值

    • 如果Callable接口方法call方法异常,在FutureTask的get方法调用时也会抛出同样的异常

    第四种:线程池 + execute

    从JDK5版本开始,java默认提供了线程池的支持,用线程池的方式运行线程可以避免线程的无限扩张导致应用宕机,同时也节省了线程频繁创建与销毁的资源与时间成本。

    pool-1-thread-5:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-2:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-4:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-4:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-4:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-1:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-4:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-3:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-2:实现线程的方式Runnable接口,但运行方式不一样,使用线程池
    pool-1-thread-5:实现线程的方式Runnable接口,但运行方式不一样,使用线程池

    线程池ExecutorService使用execute方法运行Runnable接口run方法的线程实现,execute方法与run方法的共同特点是没有返回值。

    public class FifthWay implements Callable<String> {
        @Override
        public String call() throws Exception {
            return Thread.currentThread().getName() + ":Callable接口带返回值,可以抛出异常";
        }
    
        //模拟测试
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            //保存多线程执行结果
            List<String> retList = new ArrayList<>();
            //创建一个固定大小的线程池
            ExecutorService threadPool = Executors.newFixedThreadPool(5);
            for(int i = 0;i < 10;i++){
                Future<String> future = threadPool.submit(new FifthWay());
                retList.add(future.get());
            }
            //java8 语法,打印retlist
            retList.forEach(System.out::println);
        }
    }

    从上面的结果中可以看出,线程池中包含五个线程。线程运行完成之后并不销毁,而是还回到线程池,下一次执行时从线程池中获取线程资源再次运行。

    第五种:线程池 + submit

    下面的例子线程池ExecutorService使用submit方法运行Callable接口call方法的线程实现,submit方法与call方法的共同特点是存在返回值。

    • Callable接口call方法的返回值可以由泛型定义

    • ExecutorService线程池submit方法的返回值是Future

    Future的get方法可以获取call方法的返回值,同时如果call方法抛出异常,Future的get方法也会抛出异常。

    pool-1-thread-1:Callable接口带返回值,可以抛出异常
    pool-1-thread-2:Callable接口带返回值,可以抛出异常
    pool-1-thread-3:Callable接口带返回值,可以抛出异常
    pool-1-thread-4:Callable接口带返回值,可以抛出异常
    pool-1-thread-5:Callable接口带返回值,可以抛出异常
    pool-1-thread-1:Callable接口带返回值,可以抛出异常
    pool-1-thread-2:Callable接口带返回值,可以抛出异常
    pool-1-thread-3:Callable接口带返回值,可以抛出异常
    pool-1-thread-4:Callable接口带返回值,可以抛出异常
    pool-1-thread-5:Callable接口带返回值,可以抛出异常

    上文代码中有一个小小的语法糖,retList.forEach(System.out::println);Der dritte Weg: Implementieren der Callable-Schnittstelle

    #🎜🎜#Der dritte Weg besteht darin, die Callable-Schnittstelle und die Runable-Schnittstelle zu implementieren. #🎜🎜#rrreee#🎜🎜##🎜🎜#Der Unterschied ist wie folgt: #🎜🎜##🎜🎜#
    • #🎜🎜#Aufrufbarer Schnittstellen-Implementierungsthread Methode ist call , die von der Runable-Schnittstelle implementierte Thread-Methode ist run#🎜🎜#
    • #🎜🎜#Callable hat einen Rückgabewert, die Runable-Schnittstelle kann keinen Rückgabewert haben#🎜🎜#
    • #🎜🎜#Callable Der Rückgabewert des Schnittstellenmethodenaufrufs kann auf einen generischen Typ gesetzt werden. Im folgenden Beispiel wird der Datentyp String verwendet #🎜🎜#
    • #🎜🎜 #Die Aufrufmethode der aufrufbaren Schnittstellenmethode kann Ausnahmen auslösen, und die Ausführungsmethode der ausführbaren Schnittstelle kann keine Ausnahmen auslösen. Ausnahme #🎜🎜#
    • #🎜🎜#Die aufrufbare Schnittstellenmethode wird über new Thread(futureTask).start ausgeführt (). Die get-Methode von FutureTask kann die Aufrufmethode der Callable-Schnittstellenmethode erhalten Dieselbe Ausnahme wird ausgelöst, wenn die Get-Methode von FutureTask aufgerufen wird Java bietet standardmäßig Unterstützung für Thread-Pools. Durch das Ausführen von Threads in einem Thread-Pool kann eine unendliche Erweiterung von Threads vermieden werden, die zu Ausfallzeiten bei Anwendungen führt. Außerdem werden Ressourcen und Zeitkosten durch häufiges Erstellen und Zerstören von Threads eingespart. #🎜🎜#rrreee#🎜🎜##🎜🎜#Thread-Pool ExecutorService verwendet die Execute-Methode, um die Thread-Implementierung der Run-Methode der Runnable-Schnittstelle auszuführen. Das gemeinsame Merkmal der Execute-Methode und der Run-Methode ist, dass es keine gibt Rückgabewert. #🎜🎜##🎜🎜#rrreee#🎜🎜#Wie aus den obigen Ergebnissen ersichtlich ist, enthält der Thread-Pool fünf Threads. Nachdem der Thread abgeschlossen ist, wird er nicht zerstört, sondern an den Thread-Pool zurückgegeben. Die Thread-Ressourcen werden aus dem Thread-Pool abgerufen und bei der nächsten Ausführung erneut ausgeführt. #🎜🎜##🎜🎜#Der fünfte Typ: Thread-Pool + Submit#🎜🎜##🎜🎜##🎜🎜#Der folgende Beispiel-Thread-Pool ExecutorService verwendet die Submit-Methode, um die Thread-Implementierung der Aufrufmethode der Callable-Schnittstelle auszuführen. Die Submit-Methode ist dasselbe wie die Call-Methode. Das gemeinsame Merkmal der Methoden ist das Vorhandensein eines Rückgabewerts. #🎜🎜##🎜🎜#
      • #🎜🎜#Aufrufbare Schnittstelle Der Rückgabewert der Aufrufmethode kann durch Generics#🎜🎜#
      • #🎜🎜#Der Rückgabewert der Submit-Methode des ExecutorService-Thread-Pools ist Future#🎜🎜#
    • #🎜🎜##🎜🎜#Die Get-Methode von Future kann den Rückgabewert der Call-Methode abrufen und #🎜🎜#Wenn die Aufrufmethode eine Ausnahme auslöst, löst auch die get-Methode von Future eine Ausnahme aus. #🎜🎜##🎜🎜#rrreee#🎜🎜#Der obige Code enthält einen kleinen Syntaxzucker: retList.forEach(System.out::println); ist eine von Java8 bereitgestellte Methodenreferenz #🎜🎜#rrreee

    Das obige ist der detaillierte Inhalt vonWie erstelle und führe ich Threads in Java aus?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen