page contents

深入浅出玩转Java多线程

本文讲述了Java教程——深入浅出玩转Java多线程!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

attachments-2023-09-DYBKP5cJ6508fa3826d00.jpg本文讲述了Java教程——深入浅出玩转Java多线程!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

Java多线程是Java编程语言的一个特性,它允许程序在同一时间执行多个任务。使用多线程可以充分利用计算机的多核处理器,提高程序的性能和响应速度。

本文将介绍一下Java多线程的用法。

基础介绍

什么是多线程

指的是在一个进程中同时运行多个线程,每个线程都可以独立执行不同的任务或操作。 与单线程相比,多线程可以提高程序的并发性和响应能力。

什么是进程

是指正在运行的程序的实例。

每个进程都拥有自己的内存空间、代码、数据和文件等资源,可以独立运行、调度和管理。在操作系统中,进程是系统资源分配的最小单位,是实现多任务的基础。

Java多线程

Java多线程是指在一个Java程序中同时执行多个线程,它可以提高程序的并发性和响应能力。Java中实现多线程的方式:

继承Thread类

实现Runnable接口

Executor框架

Callable

Future

线程池

继承Thread类

继承Thread类是实现多线程的一种方式,只需要继承Thread类并重写run()方法即可。

public class ThreadDemo {

    public static void main(String[] args) {

        // 创建10个线程并启动

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

            MyThread thread = new MyThread(i);

            thread.start();

        }

    }

}

 

class MyThread extends Thread {

    private int id;

 

    public MyThread(int id) {

        this.id = id;

    }

 

    public void run() {

        System.out.println("Thread " + id + " is running");

        try {

            Thread.sleep(1000);  // 模拟任务执行时间

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

    }

}

以上代码中,首先创建了一个ThreadDemo类,在main函数中创建了10个线程,并启动这些线程。

每个线程都是MyThread类的实例,MyThread类继承了Thread类,并重写了run()方法,在方法中模拟了一个需要执行1秒钟的任务。

在main函数中,通过创建MyThread类的实例,并调用start()方法启动线程。start()方法会调用线程的run()方法,在run()方法中执行线程的任务。

实现Runnable接口

另一种实现多线程的方式是实现Runnable接口,需要实现run()方法,并将实现了Runnable接口的对象传递给Thread类的构造函数。

public class RunnableDemo {

    public static void main(String[] args) {

        // 创建10个线程并启动

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

            Runnable task = new MyTask(i);

            Thread thread = new Thread(task);

            thread.start();

        }

    }

}

 

class MyTask implements Runnable {

    private int id;

 

    public MyTask(int id) {

        this.id = id;

    }

 

    public void run() {

        System.out.println("Thread " + id + " is running");

        try {

            Thread.sleep(1000);  // 模拟任务执行时间

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

    }

}

以上代码中,创建了一个RunnableDemo类,在main函数中创建了10个线程,并启动这些线程。

每个线程都是MyTask类的实例,MyTask类实现了Runnable接口,并重写了run()方法,在方法中模拟了一个需要执行1秒钟的任务。

在main函数中,通过创建MyTask类的实例,并创建一个Thread对象,将Runnable对象作为参数传递给Thread构造方法,最后调用start()方法启动线程。start()方法会调用线程的run()方法,在run()方法中执行线程的任务。

在使用实现Runnable接口实现多线程时,可以更好地分离任务和线程,并提高代码的可扩展性和可维护性。

如果需要添加更多的线程或任务,只需要创建更多的Runnable实例,并创建对应的Thread对象即可,不需要创建更多的线程类,并且可以更好地重用代码。

Executor框架

Executor框架是Java提供的一个线程池框架,用于管理和调度多个线程。通过Executor框架,可以更方便地实现多线程,避免手动管理线程带来的复杂性和风险。

Executor框架的核心接口是Executor和ExecutorService,

Executor是一个简单的线程池接口,只有一个execute()方法,用于提交一个Runnable任务给线程池执行。

ExecutorService是Executor的扩展接口,提供了更多的管理和调度线程的方法,如submit()、shutdown()、awaitTermination()等。

使用Executor框架实现多线程,通常需要以下步骤:

创建一个ExecutorService对象,可以使用Executors类提供的静态方法创建线程池,如newFixedThreadPool()、newCachedThreadPool()、newSingleThreadExecutor()等。

将需要执行的任务封装成一个Runnable或Callable对象,可以使用Java中的匿名内部类或Lambda表达式来创建。

将任务提交给ExecutorService对象执行,可以使用submit()方法提交Callable对象,或使用execute()方法提交Runnable对象。

在程序完成时,调用shutdown()方法关闭线程池,或使用awaitTermination()方法等待所有线程执行完毕。

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class ExecutorDemo {

    public static void main(String[] args) {

        // 创建一个包含10个线程的线程池

        ExecutorService executor = Executors.newFixedThreadPool(10);

 

        // 提交10个任务给线程池执行

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

            executor.execute(new MyTask(i));

        }

 

        // 关闭线程池

        executor.shutdown();

    }

}

 

class MyTask implements Runnable {

    private int id;

 

    public MyTask(int id) {

        this.id = id;

    }

 

    public void run() {

        System.out.println("Thread " + id + " is running");

        try {

            Thread.sleep(1000);  // 模拟任务执行时间

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

    }

}

在上面的例子中,先创建了一个ExecutorDemo类,在main函数中创建了一个包含10个线程的线程池。

每个线程池中的线程都可以执行MyTask类的实例,MyTask类实现了Runnable接口,并重写了run()方法,在方法中模拟了一个需要执行1秒钟的任务。

在main函数中,创建MyTask类的实例,并调用ExecutorService的execute()方法提交给线程池执行。

execute()方法会将任务提交给线程池中的一个空闲线程执行。

最后调用ExecutorService的shutdown()方法关闭线程池。

需要注意的是,shutdown()方法会等待所有线程执行完毕后才会关闭线程池,如果需要立即关闭线程池,可以使用shutdownNow()方法。

Callable实现多线程

Callable是Java中的一个接口,与Runnable接口类似,都用于封装一个线程执行的任务。

不同的是,Callable接口的call()方法可以返回一个结果,而Runnable接口的run()方法没有返回值。

使用Callable实现多线程,通常需要以下步骤:

创建一个实现了Callable接口的类,实现call()方法,并在方法中编写线程执行的代码。

创建一个ExecutorService对象,可以使用Executors类提供的静态方法创建线程池,如newFixedThreadPool()、newCachedThreadPool()、newSingleThreadExecutor()等。

将Callable对象提交给ExecutorService对象执行,可以使用submit()方法提交。

调用Future对象的get()方法获取Callable线程执行的结果。

在程序完成时,调用shutdown()方法关闭线程池,或使用awaitTermination()方法等待所有线程执行完毕。

import java.util.concurrent.*;

public class CallableDemo {

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

        // 创建一个线程池

        ExecutorService executor = Executors.newFixedThreadPool(10);

 

        // 提交10个Callable任务给线程池执行

        Future<Integer>[] results = new Future[10];

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

            Callable<Integer> task = new MyTask(i);

            results[i] = executor.submit(task);

        }

 

        // 输出Callable任务的执行结果

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

            Integer result = results[i].get();

            System.out.println("Task " + i + " result is " + result);

        }

 

        // 关闭线程池

        executor.shutdown();

    }

}

 

class MyTask implements Callable<Integer> {

    private int id;

 

    public MyTask(int id) {

        this.id = id;

    }

 

    public Integer call() throws Exception {

        System.out.println("Task " + id + " is running");

        Thread.sleep(1000);  // 模拟任务执行时间

        return id * 10;

    }

}

首先创建一个线程池,然后提交10个Callable任务给线程池执行。每个Callable任务都是MyTask类的实例,MyTask类实现了Callable接口,并重写了call()方法,在方法中模拟了一个需要执行1秒钟的任务,并返回一个结果。

详细解释如下:

创建一个线程池,通过调用Executors的静态方法newFixedThreadPool(10),创建了一个固定大小为10的线程池。

在for循环中,通过创建MyTask类的实例,将其封装为Callable对象,并通过ExecutorService的submit()方法提交给线程池执行。submit()方法会返回一个Future对象,代表了Callable任务的执行结果。

在for循环中,通过Future数组记录每个Callable任务的执行结果,可以通过调用get()方法获取Callable任务的执行结果。如果Callable任务还没有执行完成,get()方法会阻塞当前线程,直到任务执行完成并返回结果。如果任务执行过程中发生异常,get()方法会抛出ExecutionException异常。

在任务完成后,可以通过调用Future对象的get()方法获取任务的执行结果,并打印输出。

最后调用ExecutorService的shutdown()方法关闭线程池,应该在所有任务执行完成后才能关闭线程池。

注意,在使用Callable实现多线程时,要考虑线程安全、同步机制、任务调度和管理等问题,以确保程序的正确性和稳定性。

同时,由于Callable任务的执行时间可能会比较长,可以设置超时时间来避免任务执行时间过长导致的程序阻塞。

Future实现多线程

Future是Java中的一个接口,用于异步获取任务执行结果。

在多线程编程中,可以使用Future来获取异步任务的执行结果,以便在任务完成后进行处理或展示。

使用Future实现多线程,需要以下步骤:

创建一个实现了Callable接口的类,实现call()方法,并在方法中编写线程执行的代码。

创建一个ExecutorService对象,可以使用Executors类提供的静态方法创建线程池,如newFixedThreadPool()、newCachedThreadPool()、newSingleThreadExecutor()等。

将Callable对象提交给ExecutorService对象执行,可以使用submit()方法提交,submit()方法会返回一个Future对象。

调用Future对象的get()方法获取Callable线程执行的结果。如果任务还没有执行完成,get()方法会阻塞当前线程直到任务执行完成并返回结果。

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.*;

public class FutureDemo {

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

        // 创建一个线程池

        ExecutorService executor = Executors.newFixedThreadPool(10);

 

        // 提交10个Callable任务给线程池执行

        List<Future<Integer>> results = new ArrayList<>();

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

            Callable<Integer> task = new MyTask(i);

            Future<Integer> result = executor.submit(task);

            results.add(result);

        }

 

        // 输出Callable任务的执行结果

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

            Integer result = results.get(i).get();

            System.out.println("Task " + i + " result is " + result);

        }

 

        // 关闭线程池

        executor.shutdown();

    }

}

 

class MyTask implements Callable<Integer> {

    private int id;

 

    public MyTask(int id) {

        this.id = id;

    }

 

    public Integer call() throws Exception {

        System.out.println("Task " + id + " is running");

        Thread.sleep(1000);  // 模拟任务执行时间

        return id * 10;

    }

}

在以上示例中:

首先创建了一个线程池,然后提交10个Callable任务给线程池执行。每个Callable任务都是MyTask类的实例,MyTask类实现了Callable接口,并重写了call()方法,在方法中模拟了一个需要执行1秒钟的任务,并返回一个结果。

在main函数中,使用List记录每个Callable任务的执行结果的Future对象,并在任务完成后通过调用get()方法获取Callable任务的执行结果。如果任务还没有执行完成,get()方法会阻塞当前线程直到任务执行完成并返回结果。

最后关闭线程池。

线程池实现多线程

线程池是Java中提供的一个用于管理和复用多个线程的框架,可以有效地提高多线程应用程序的性能和可靠性。

使用线程池实现多线程,通常需要以下步骤:

创建一个线程池,可以使用Executors类提供的静态方法创建线程池,如newFixedThreadPool()、newCachedThreadPool()、newSingleThreadExecutor()等。

创建一个实现了Runnable接口或Callable接口的类,实现run()方法或call()方法,并在方法中编写线程执行的代码。

将Runnable对象或Callable对象提交给线程池执行,可以使用submit()方法提交,submit()方法会返回一个Future对象。

关闭线程池,可以调用shutdown()方法或shutdownNow()方法。

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.*;

public class ThreadPoolDemo {

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

        // 创建一个包含10个线程的线程池

        ExecutorService executor = Executors.newFixedThreadPool(10);

 

        // 提交10个任务给线程池执行,并记录每个任务的执行结果

        List<Future<Integer>> results = new ArrayList<>();

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

            Callable<Integer> task = new MyTask(i);

            Future<Integer> result = executor.submit(task);

            results.add(result);

        }

 

        // 等待所有任务执行完成

        executor.shutdown();

        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);

 

        // 输出所有任务的执行结果

        int total = 0;

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

            try {

                Integer result = results.get(i).get();

                System.out.println("Task " + i + " result is " + result);

                total += result;

            } catch (InterruptedException e) {

                e.printStackTrace();

            } catch (ExecutionException e) {

                System.out.println("Task " + i + " execution error: " + e.getCause().getMessage());

            }

        }

        System.out.println("Total result is " + total);

    }

}

 

class MyTask implements Callable<Integer> {

    private int id;

 

    public MyTask(int id) {

        this.id = id;

    }

 

    public Integer call() throws Exception {

        System.out.println("Task " + id + " is running");

        Thread.sleep(2000);  // 模拟任务执行时间

        if (id % 2 == 0) {

            throw new RuntimeException("Task " + id + " execution error");

        }

        return id * 10;

    }

}

在以上示例中,首先创建了一个包含10个线程的线程池,然后提交10个任务给线程池执行。每个任务都是MyTask类的实例,MyTask类实现了Callable接口,并重写了call()方法,在方法中模拟了一个需要执行2秒钟的任务,并返回一个结果。

其中,如果任务的id是偶数,会抛出一个运行时异常。

在main函数中,使用List记录每个任务的执行结果的Future对象,并在任务完成后通过调用get()方法获取任务的执行结果。

如果任务还没有执行完成,get()方法会阻塞当前线程直到任务执行完成并返回结果。

在所有任务提交给线程池后,调用ExecutorService的shutdown()方法关闭线程池,并调用awaitTermination()方法等待所有任务执行完成。

最后输出所有任务的执行结果,并计算所有任务的执行结果的总和。

总结

总之,Java多线程是提高程序并发性和响应能力的重要手段,需要掌握多线程的实现方式、同步机制、线程之间的通信机制等,以确保多线程程序的正确性和稳定性。

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

想高效系统的学习Java编程语言,推荐大家关注一个微信公众号:Java圈子。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Java入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2023-03-2AoKIjPQ64014b4ad30a3.jpg

  • 发表于 2023-09-19 09:32
  • 阅读 ( 223 )
  • 分类:Java开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
小柒
小柒

1470 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1470 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章