java学习——多线程程序设计(1)

一、编写线程程序

  构造线程类的方式主要有两种:一种是通过构造类java.lang.Thread的子类,另一种是通过构造实现接口java.lang.Runnable的类。

  1.通过类Thread的子类构造线程

    编写Thread子类的过程中,一个很重要的步骤是编写run成员方法,这个成员方法实际上是对类java.lang.Thread的成员方法run()的覆盖,其中包含了线程所需要执行的代码。但是启动或运行线程并不是直接调用成员方法run的,二是调用类Thread的成员方法start()启动线程的。如果直接调用成员方法run,则一般来说会立即执行成员方法run,从而失去线程的特征。在调用成员方方法start之后,java虚拟机会自动启动线程,从而由java虚拟机进一步统一调度线程,实现各个线程一起并发执行。java虚拟机决定是否开始以及何时开始运行该线程,而线程的运行实际上就是执行线程的成员方法run的。在main中创建两个并发执行的线程,在main运行结束之后,线程仍然能够继续运行。

  2.通过接口Runnable构造线程

    通过接口java.lang.Runnable构造线程是在构造线程过程中可能出现的多重继承问题的一种解决方法。编写实现接口java.lang.Runnable的类的一般格式如下。

    public class A extends B implements Runnable{

      //类体的其他部分

      public void run(){

      //成员方法run的方法体

      }

      //类体的其他部分

    }

    构造和启动线程的方法如下:

    A a=new A();

    Thread t=new Thread(a);

    t.start();

  3.后台(deamon)线程

    线程可以分为后台线程(deamon thread)和用户线程(user thread)。后台线程也称为守护线程或精灵线程。它与用户线程的区别只是在于当在一个线程中只有后台线程在运行时,程序会立即退出。如果一个程序还存在正在运行的用户线程,则该程序不会中止。在默认情况下,线程是用户线程。可以通过类java.lang.Thread的成员方法public final boolean isDeamon()来判断一个线程是用户线程还是后台线程。可以使用类java.lang.Thread的成员方法public final void setDeamon(boolean on)将线程状态在用户线程和后台线程之间切换,但切换必须在线程启动之前。

  4.线程组

    线程可以通过线程组(类java.lang.ThreadGroup的实例对象)来进行管理。这里的线程组是一些线程和线程组的集合。因为线程组可以包含其他线程组,所以线程组实际上形成了一个树状的体系结构。除了树状根部的线程组之外,每个线程组都有一个父线程组。一个线程组的父线程组就是包含该线程组的线程组。构造线程组可以通过类java.lang.ThreadGroup的两个构造方法。其中一个构造方法是public ThreadGroup(String name),参数name用来指定线程组的名称。这时所构造出来的线程组的父线程组是当前线程所在的线程组。另一个构造方法是public ThreadGroup(ThreadGroup parent,String name),参数parent指定父线程组,参数name指定新构造的线程组的名称。

    将一个线程添加到一个线程组中一般是在创建线程时通过线程的构造方法的参数指定线程组。例如类java.lang.Thread的构造方法public Thread(ThreadGroup group,String name)。

    Thread中的方法:

    public static int activeCount()返回在当前线程组中的线程个数

    public static Thread currentThread()返回当前线程

    public final ThreadGroup getThreadGroup()返回该线程所在的线程组

    public final String getName()返回该线程的名称

    ThreadGroup的方法:

    public final ThreadGroup getParent()返回该线程组的父线程组

    public final String getName()返回该线程组的名称

    public int activeCount()返回所估算出来的在该线程组及其以下各级线程组中的线程总个数

    public int enumerate(Thread[] list)将在该线程组及其以下各级线程组中的线程拷贝到数组list中,并返回放在数组list中的线程个数。

    public int enumerate(ThreadGroup[] list)将在该线程组及其以下各级线程组中的线程组拷贝到数组list中,并返回放在数组list中的线程组个数。

二、线程的声明周期

    线程一般要经历新生态、就绪态、运行态和死亡态4个基本状态。有时由于线程的并发等原因,还可能进入阻塞态。另外,根据程序的需要,线程还有可能进入等待态和睡眠态。

    当创建了类Thread或者子类的实例对象时,一个新的线程也就产生了,这时线程自动进入新生态。new 类Thread的子类的构造方法(构造方法调用参数列表)/ new Thread (new 实现接口Runnable的类的构造方法(构造方法调用参数列表))

    刚刚创建的线程还不能与其他线程一同并发运行。这时需要调用线程的成员方法start,使得线程进入就绪态。只有处于就绪态的线程才能参与java虚拟机对线程的调度。

    java虚拟机按照一定的调度规则让一些处于就绪态的线程进入运行态。进入运行态的线程自动执行在线程的成员方法run的代码。java虚拟机对线程的调度首先要根据线程的优先级。最小优先级1,最大优先级5。

      java.lang.Thread中一些方法用来设置优先级:

      public final void setPriority(int newPriority)//给当前前程设置优先级,当参数new Priority比线程所允许的最大优先级还要大时,所设置的优先级为所允许的最大优先级。一个线程所允许的最大优先级与该线程所在的线程组的所允许的最大优先级一样

      java.lang.ThreadGroup中的一些方法:

      public final int getMaxPriority()//返回该线程组所允许的最大优先级

      public final void setMaxPriority(int pri)//给线程组设置所允许的最大优先级

    在线程调度的过程中,如果存在多个处于就绪态的线程,则优先级高的线程优先进入运行态。如果存在资源共享冲突,则优先级高的线程优先占用该资源。如果线程的优先级都一样,则java虚拟机随机调度这些线程进入运行态或占用资源。如果多个线程共享资源,并且只能有限个线程同时占用该资源,则java虚拟机在调度就绪态的线程时会让一些处于就绪态的线程占用这些资源,而其他处于就绪态的线程就会因为资源短缺而自动进入阻塞态。处于阻塞态的线程在所需要的资源准备就绪时会自动重新进入就绪态,再次由java虚拟机进行调度。

    处在运行态的线程在调用类Thread的成员方法public static void sleep(long millis) throws InterruptedException之后,自动进入睡眠态。在过了指定的睡眠时间之后,线程会继续运行,即开始执行在导致进入睡眠态的sleep语句之后的语句。

    为了使得多个线程之间保持同步,处于运行态的线程还可能调用类java.lang.Object的成员方法wait,从而进入等待态。当等待的时间到或者别的线程调用了类java.lang.Object的成员方方法notify或notifyAll时,处于等待态的线程有可能重新回到就绪态,由java虚拟机重新进行调度。

    在执行完run方法中的代码之后,线程自动进入死亡态。

   

    

 

    

转载于:https://www.cnblogs.com/HelloMoying/p/5948630.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值