【Java】《Java多线程编程核心技术》1多线程技能

    xiaoxiao2024-11-12  86

    目录

     

    前言

    导图展示  

    进程和线程的概念

    一、概念理解

    二、多线程实现方式

    常用线程方法

    小结


    前言

         小编最近在看一本多线程书籍《Java多线程编程核心技术》,里面讲到了线程的一些基础知识,书中全部用案例来讲解技术点的实现,使读者看到代码及运行结果后就可以知道此此项目要解决的是什么问题。

        本书就像“瑞士军刀”一样,精短小,但却非常锋利,可帮读者快速学习知识并解决问题。

       下面是读第一章内容后的一些简单总结。

    导图展示  

    进程和线程的概念

    一、概念理解

    进程:操作系统结构的基础,是一次程序的执行,是系统资源分配和调度的一个独立单位。

    线程:进程中独立运行的子任务。

    多线程优点:最大限度利用CPU空闲时间,提升系统运行效率,多线程是异步运行的,单线程的是同步运行的。

    二、多线程实现方式

        继承Thread类,实现Runnable接口;

    书中提到了这两种,现在多线程实现还有其他两种:

        实现Callable接口通过FutureTask包装器来创建Thread线程,

        使用ExecutorService、Callable、Future实现有返回结果的多线程。

    1.继承Thread类创建线程

       Thread类本质上是实现了Runnable接口的一个实例,代表一个线程的实例。

       启动线程使用start()实例方法,这是一个native方法,将启动一个新线程,并默认执行run()方法,这个run()方法是通过自己的类重写run()方法。

    public class MyThread extends Thread {   public void run() {    System.out.println("MyThread.run()");   } } MyThread myThread1 = new MyThread(); MyThread myThread2 = new MyThread(); myThread1.start(); myThread2.start();

    2.实现Runnable接口创建线程

      如果自己的类已经extends另一个类,就无法继承Thread类,Java具有单继承性。此时,可以实现一个Runnable接口。

    public class MyThread extends OtherClass implements Runnable {   public void run() {    System.out.println("MyThread.run()");   } }

       为了启动MyThread,需要实例化一个Thread,并传入参数myThread实例,这个Thread类的一个带参的构造方法。

    MyThread myThread = new MyThread(); Thread thread = new Thread(myThread); thread.start();

      事实上,当传入一个Runnable target参数给Thread实例后,Thread实例的run()方法会调用target.run()方法,这就是通过一个线程启动另一个线程。

    public void run() {   if (target != null) {    target.run();   } }

    3.实现Callable接口通过FutureTask包装器来创建Thread线程

    Callable接口(只有一个方法),定义如下:

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

    实现Callable接口

    public class SomeCallable<V> extends OtherClass implements Callable<V> { @Override public V call() throws Exception { // TODO Auto-generated method stub return null; } }

    使用Callable接口和FutureTask包装器创建线程

    Callable<V> oneCallable = new SomeCallable<V>(); //由Callable<Integer>创建一个FutureTask<Integer>对象: FutureTask<V> oneTask = new FutureTask<V>(oneCallable); //注释:FutureTask<Integer>是一个包装器,它通过接受Callable<Integer>来创建,它同时实现了Future和Runnable接口。 //由FutureTask<Integer>创建一个Thread对象: Thread oneThread = new Thread(oneTask); oneThread.start(); //至此,一个线程就创建完成了。

    4.使用ExecutorService、Callable、Future实现有返回结果的线程

       ExecutorService、Callable、Future三个接口都属于Executor框架,返回结果的线程是在JDK1.5中引入的新特征;

       返回值的任务必须实现Callable接口,无返回值的任务必须实现Runnable接口;

       执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的object了。

     (get方法是阻塞的,如果线程无返回结果,get方法会一直等待)

    具体实例

    import java.util.concurrent.*; import java.util.Date; import java.util.List; import java.util.ArrayList; /** * 有返回值的线程 */ @SuppressWarnings("unchecked") public class Test { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println("----程序开始运行----"); Date date1 = new Date(); int taskSize = 5; // 创建一个线程池 ExecutorService pool = Executors.newFixedThreadPool(taskSize); // 创建多个有返回值的任务 List<Future> list = new ArrayList<Future>(); for (int i = 0; i < taskSize; i++) { Callable c = new MyCallable(i + " "); // 执行任务并获取Future对象 Future f = pool.submit(c); // System.out.println(">>>" + f.get().toString()); list.add(f); } // 关闭线程池 pool.shutdown(); // 获取所有并发任务的运行结果 for (Future f : list) { // 从Future对象上获取任务的返回值,并输出到控制台 System.out.println(">>>" + f.get().toString()); } Date date2 = new Date(); System.out.println("----程序结束运行----,程序运行时间【" + (date2.getTime() - date1.getTime()) + "毫秒】"); } } class MyCallable implements Callable<Object> { private String taskNum; MyCallable(String taskNum) { this.taskNum = taskNum; } public Object call() throws Exception { System.out.println(">>>" + taskNum + "任务启动"); Date dateTmp1 = new Date(); Thread.sleep(1000); Date dateTmp2 = new Date(); long time = dateTmp2.getTime() - dateTmp1.getTime(); System.out.println(">>>" + taskNum + "任务终止"); return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】"; } }

    借鉴博客:https://www.cnblogs.com/felixzh/p/6036074.html

    常用线程方法

    一、 主要方法

    二、具体线程方法介绍

    1.线程名称 getName();

    2. 当前线程 CurrentThread()

    3.判断线程是否在执行:isAlive()

    4.线程强制运行:join()

      可以通过join()方法使得一个线程强制运行,线程强制运行期间,其他线程无法运行,必须等待此线程完成之后,才可以继续。

    5.线程的休眠:sleep()

    throws表示如果有异常要在调用此方法处处理异常

    public static void sleep(long milis,int nanos) throws InterruptedException

    6.线程的中断:interrupt()

        一个线程可以被另一个 线程中断其操作的状态。

         使用return,中断线程执行

    7.后台线程:setDaemon()

        在Java中,只要一个线程没有执行完(一个线程在运行),则整个Java的进程不会消失,所以此时可以设置一个后台线程,即使java线程结束,后台线程依旧会继续执行。

    class MyThread implements Runnable{ // 实现Runnable接口 public void run(){ // 覆写run()方法      int i=0; while(true){    //设置死循环,这样来实现线程不断运行,设置后台运行。 System.out.println(Thread.currentThread().getName() + "在运行。"+i) ; } } }; public class ThreadDaemonDemo{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 实例化Runnable子类对象 Thread t = new Thread(mt,"线程"); // 实例化Thread对象 t.setDaemon(true) ; // 此线程在后台运行 t.start() ; // 启动线程 } };

    8.线程优先级 getPriority()

    优先级分为最低,最高,普通三个(Thread.MIN_PRIORITY,Thread.MAX_PRIORITY,Thread.NORM_PRIORITY)

    9.线程的礼让:yield()

    借鉴博客:https://www.cnblogs.com/alsf/p/5651888.html

    小结

        通过总结,对于线程的新技能,小编get到了!

                                                                               感谢您的访问!

    最新回复(0)