• java多线程实现方式


    一、什么是线程?

        线程:程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位。

        多线程:单个程序中同时运行多个线程完成不同的工作,称为多线程。

        特点:

        1)轻量级的进程,程序运行流中可执行的最小单元,线程不拥有系统资源,多个线程共享进程拥有的资源。

        2)一个线程可以创建另外一个线程,多个线程可以并发执行。

        3)多个线程在系统运行中抢占资源,会出现间断性,我们看到的是并行执行,其实在有先后顺序的。

        4)一个进程至少包含一个线程,即主线程。

     

    二、线程有哪些状态?

     

     

        线程具有:新建,就绪,运行,阻塞,终止五种状态。

        ①新建:线程被创建,没有执行任何方法,如,Thread th = new Thread()。

        ②就绪:当调用线程的start方法时,就会触发线程状态变更为就绪态,等待cpu来调用。处于就绪态的线程才会被cpu调度,单cpu不是立即执行它。

        ③运行:当cpu发起对此线程调用时,它就进入了运行态。

        ④阻塞:当线程由于某种原因,不再拥有cpu使用权,它就会被阻塞。

            阻塞有以下几种情况:

         1)sleep(long mills):参数为毫秒数,使线程在指定的时间内进入阻塞,时间一过,进入就绪态。

         2)suspend() 和 resume():suspend会让线程挂起,必须执行resume进行线程的恢复。

         3)yield():与sleep()类似,但是不能由用户指定暂停多长时间,只能出让机会给同优先级的线程,且不进入阻塞。如同排队,前面的人和后面的人交换位置,但是还处在队伍中。

         4)wait() 和 notify():wait() 使线程进入阻塞状态,有两种形式,一种指定毫秒数,另一种无参。前者可通过notify()唤起或者超过指定时间自动恢复;后者必须通过notify()唤起。

        5)同步阻塞:等待同步锁资源。多线程竞争同一个资源时,只能一个线程获得锁,其它的线程要等待。

        ⑤终止:线程执行完毕,或者出现异常,线程结束。

         

    三、如何创建线程?

        java线程的实现方式有三种:继承Thread类、实现Runnable接口,使用Callable和FutureTask(可以有返回值)

    1、通过集成Thread类,覆写run()方法

    class MyThread extends Thread {

    @Override

    public void run() {

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

    System.out.println(Thread.currentThread().getName() + " " + i);

    }

    }

    }

     

    public class ThreadDemo {

    public static void main(String[] args) {

    System.out.println(Thread.currentThread().getName());

    MyThread th1 = new MyThread();

    MyThread th2 = new MyThread();

    th1.start();

    th2.start();

    }

    }

    输出:main

    Thread-1 0

    Thread-0 0

    Thread-1 1

    Thread-1 2

    ......

        线程要实现的逻辑写在run方法中,通过执行线程的start()方法,使线程进入就绪状态,等待CPU分配资源。

        可以看到两个线程并行执行,且随机获得CPU。

     

    2、试过实现Runnable接口,实现run()方法

    class MyThread implements Runnable {

    @Override

    public void run() {

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

    System.out.println(Thread.currentThread().getName() + " " + i);

    }

    }

    }

     

    public class ThreadDemo {

    public static void main(String[] args) {

    System.out.println(Thread.currentThread().getName());

    MyThread th = new MyThread();

    Thread t1 = new Thread(th);

    Thread t2 = new Thread(th);

    t1.start();

    t2.start();

    }

    }

    输出:main

    Thread-0 0

    Thread-0 1

    Thread-1 0

    Thread-0 2

    ......

    通过将MyThread实例传入Thread构造方法实例化Thread,调用Thread的start方法,启动线程。

     

    ps:继承Thread和实现Runnable接口有什么区别呢?

    1:前者为单继承,有局限性,但接口的方式可以实现多个。

    2:后者可以实现资源共享。

    多线程编程中,强烈建议使用Runnable

     

    3、使用Callable和Future接口创建线程。

        具体是创建Callable接口的实现类,并实现clall()方法。

        并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建线程。

     

    class MyCallable implements Callable<Integer> {

    @Override

    public Integer call() throws Exception {

    return 1;

    }

    }

     

    public class ThreadDemo {

    public static void main(String[] args)  {

    Callable<Integer> myCallable = new MyCallable();//实例化MyCallable

    FutureTask<Integer> ft = new FutureTask<>(myCallable);//通FutureTask包装

     

    Thread thread = new Thread(ft);//将FutureTask传入Thread构造,实例化线程

    thread.start();//线程启动

     

    Integer result = ft.get();//获取返回值

    System.out.println(result);

     

    }

    }

    1)实现Callable接口中的call()方法,这个是线程要执行的逻辑。

    2)FutureTask的get()方法会一直阻塞,直到call()方法执行完毕取到返回值。


    关注老姜谈技术,微信号:helojava,或者扫描下面二维码。


    每日一帖,技术鸡汤。

  • 相关阅读:
    我们如何监视所有 Spring Boot 微服务?
    如何使用 Spring Boot 实现异常处理?
    如何使用 Spring Boot 实现分页和排序?
    如何集成 Spring Boot 和 ActiveMQ?
    如何实现 Spring Boot 应用程序的安全性?
    Spring Boot 中的监视器是什么?
    如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?
    Spring 和 SpringBoot 有什么不同?
    Spring Boot 有哪些优点?
    如何在不使用BasePACKAGE过滤器的情况下排除程序包?
  • 原文地址:https://www.cnblogs.com/jiangkuan/p/6021707.html
Copyright © 2020-2023  润新知