zoukankan      html  css  js  c++  java
  • 齐头并进完成任务——Java多线程(一)

    多线程(Multithread)指的是在单个进程中同时运行多个不同的线程,执行不同的任务。多线程意味着一个程序的多行语句块并发执行。

    一、实现多线程

    1.通过继承Thread类实现多线程。

    Thread类来自java.lang包,在Thread类中定义了run()方法,想要实现多线程,必须覆写run()方法。然后使用该类的对象调用start()方法,来激活一个线程。

     1 class ThreadDemo extends Thread
     2 {
     3     public void run()
     4     {
     5         for(int i=0;i<2;++i)
     6         {
     7             System.out.println("ThreadDemo在运行!");
     8             try
     9             {
    10                 Thread.sleep(1000);
    11             }
    12             catch(InterruptedException e)
    13             {
    14                 e.printStackTrace();
    15             }
    16         }
    17     }
    18 }
    19 
    20 public class ThreadTest
    21 {
    22     public static void main(String[] args)
    23     {
    24         new ThreadDemo().start();//激活一个新的线程
    25         for(int j=0;j<2;++j)
    26         {
    27             System.out.println("main方法在运行!");
    28             try
    29             {
    30                 Thread.sleep(1000);//睡眠1s
    31             }
    32             catch(InterruptedException e)
    33             {
    34                 e.printStackTrace();
    35             }
    36         }
    37     }
    38 }

    输出结果:

    main方法在运行!
    ThreadDemo在运行!
    main方法在运行!
    ThreadDemo在运行!

    上述例子中的InterruptedException,表示中断异常类,Thread.sleep()和Object.wait()都可以抛出这类中断异常,printStackTrace()方法输出异常信息,这样就可以很清楚的看到两个线程交替执行的结果。如果去掉异常处理语句,那么运行结果如下:

    main方法在运行!
    main方法在运行!
    ThreadDemo在运行!
    ThreadDemo在运行!

    这个运行结果貌似不是多线程并发执行,但事实上因为循环次数过少,线程运行并没有超过时间片t,所以先把main方法执行的主线程的for循环执行完毕,再转去执行ThreadDemod的线程。(具体的会在第二部分线程的状态中叙述)

    2.通过Runnable接口实现多线程。

     因为接口可以实现多继承的原因,Runnable接口实现多线程机制更加常用。

     1 class RunnableDemo implements Runnable
     2 {
     3     public void run()
     4     {
     5         for(int i=0;i<2;++i)
     6         {
     7             System.out.println("RunnableDemo在运行!");
     8             try
     9             {
    10                 Thread.sleep(1000);
    11             }
    12             catch(InterruptedException e)
    13             {
    14                 e.printStackTrace();
    15             }
    16         }
    17     }
    18 }
    19 
    20 public class ThreadTest
    21 {
    22     public static void main(String[] args)
    23     {
    24         RunnableDemo r = new RunnableDemo();
    25         new Thread(r).start();//使用Thread类的start()方法启动线程
    26         for(int i=0;i<2;++i)
    27         {
    28             System.out.println("main方法在运行!");
    29             try
    30             {
    31                 Thread.sleep(1000);
    32             }
    33             catch(InterruptedException e)
    34             {
    35                 e.printStackTrace();
    36             }
    37         }
    38     }
    39 }

    值得一提的是,Runnable接口中只有一个run()方法,所以激活一个新线程仍然使用Thread类的start()方法。

    new Thread(r).start();Thread类的构造方法,可以将一个Runnable接口(及其子类)的实例化对象作为参数去实例化Thread类对象。

    3.两种多线程实现机制的联系与区别

    联系:Thread类实现Runnable接口,即Thread类是Runnable的一个子类。

    区别:Thread类很难实现资源共享,每个Thread实例都是在独自运行自己的线程,但能通过静态变量实现资源共享;Runnable接口可以直接达到资源共享的目的。

    ***注意:事实上,上述两个示例程序的运行结果都不唯一,这个错误就是和线程运行的时间片和相关临界区有关。

    二、线程的状态

    每个Java程序都有一个默认的主线程,对于Java应用程序,主线程是main方法执行的线程。要想实现多线程,必须在主线程中创建新的线程对象。

    1.线程具有5种状态:创建、就绪、运行、阻塞、终止。关系如下图:

                                                           

    创建:ThreadDemo t = new ThreadDemo();

    就绪:t.start();

    运行:执行run()方法。

    阻塞:暂时停止执行,原因可能是:调用sleep()、调用wait()、发生I/O阻塞、调用join()方法、不能获得对象锁。

    终止:线程执行完毕。

    2.线程的优先级

    Thread类定义的常量来设置优先级:MAX_PRIORITY(10)、NORM_PRIORITY(5)、MIN_PRIORITY(1)。

    三、操作线程的方法

    操作线程的主要方法在Thread类中,下面介绍一些常用的方法:

    1.getName()和setName()取得和设置线程名称

    Thread t = Thread.currentThread();//静态方法,返回当前正在运行的线程
    String name = t.getName();//取得线程的名称
    t.setName("线程2—1");//设置线程的名称

    2.isAlive()方法——判断线程是否启动

    ThreadDemo t = new ThreadDemo();
    Boolean b = t.isAlive();//true或false

    3.setDaemon()方法——转变为守护线程

    ThreadDemo t = new ThreadDemo();
    t.setDaemon(true);//设置守护线程,必须在start()方法前面
    t.start();

    当进程中只剩下守护线程的时候,进程才会结束。

    4.join()方法——线程联合

    try {
            t.join();
        } 
    catch (InterruptedException e)
    {
    e.printStackTrace(); }

    a线程正在运行——b.join();——a线程挂起,b线程强制运行——b线程运行结束——a线程继续运行。

    5.interrupt()方法——线程中断

       isInterrupt()方法——判断线程是否处于中断状态

    t.interrupt();
    Boolean b = t.isInterrupted();

    当一个线程运行时,另一个线程可以调用另外一个线程对应的interrupt()方法来中断它。

    ***注意:调用interrupt()方法并不会使正在执行的线程停止执行,它只对调用wait、join、sleep等方法或由于I/O操作等原因受阻的线程产生影响,使其退出暂停执行的状态。

                  即:interrupt()对正在运行的线程是不起作用的,只有对阻塞的线程有效。

  • 相关阅读:
    Java WebService入门实例
    Maven是什么
    for 循环
    2.4 DevOps工程师的故事:构建运行时的严谨性
    2.3.3 构建微服务的入口:Spring Boot控制器
    2.3.2 引导Spring Boot应用程序:编写引导类
    2.1.3 互相交流:定义服务接口
    第2章 使用Spring Boot构建微服务
    第1章 欢迎来到Cloud和Spring
    第一次在博客园开博
  • 原文地址:https://www.cnblogs.com/wxywxy/p/6783161.html
Copyright © 2011-2022 走看看