java线程(No.7)

来源:互联网 发布:400米标准跑道数据 编辑:程序博客网 时间:2024/04/18 08:23

 

Java线程

一、     线程状态的转换

线程状态总的可分为五大状态:生、死、可运行、运行、等待/阻塞。也就是说:生是创建线程对象;可运行是调用start()方法;运行是线程调度程序选择一个线程作为当前线程是所处的状态;等待/阻塞/睡眠状态是线程有资格运行是所处的状态,换句话说,它是可运行的,如果有某事件出现,则有可能返回到可运行状态;死是线run()方法完成。

二、     阻止线程执行

  1、睡眠

Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)

线程在苏醒之前不会返回到可运行状态,当苏醒之后则返回到可运行状态。

线程睡眠原因:

                 1、线程执行太快

                 2、需要强制进入下一轮

                 3、java规范不保证合理的轮换

睡眠的位置:将Thread.sleep()的调用放线程run()之内。

三、线程的优先级和线程让步yield()

线程的让步是通过Thread.yield()来实现的。Yield()方法的作用是:暂停当前正在执行的线程对象,回到可运行状态,从而让和他一样具有相同优先级的线程运行。它在大多数情况下能将线程从运行状态转到可运行状态,但有时候会没有效果。

线程的优先级:默认的优先级是创建它的执行线程的优先级。可以通过setPriority(int newPriority)更改线程的优先级。

四、     join()方法

join()方法是让一个线程b“加入”到另一个线程a的尾部。在a执行完毕之前,b不能工作。保证当前线程停止执行,直到该线程所加入的线程完成为止。然而,如果它加入的线程没有存活,则当前线程不需要停止。它还有带超市限制的重载版本。

Void join()  //等待该程序终止

Void join(long millis)   //等待该线程终止的时间最长为millis毫秒

void join(long millis,int nanos)  //等待该线程终止的时间最长为millis  毫秒 + nanos 纳秒

例如:

for (int i = 0; i < 20; i++) {
                        System.out.println("主线程第" + i + "次执行!");
                        if (i > 2) try { 
                          //t1线程合并到主线程中,主线程停止执行过程,转而执行t1线程,直到t1执行完毕后继续。
                                t1.join();
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
等同于:

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

   System.out.println("主线程第" + i + "次执行!");

   if(i==3){

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

        System.out.println("线程1第" + j + "次执行!");

     }

   }

}

五、线程的同步与锁

1、同步问题提出

线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。解决问题的方法:将资源共享的部分使用synchronized关键字同步方法。例如:

错误的代码:

public void run(){

   try {

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

        System.out.println(t.tickets);

        t.tickets--;

        Thread.sleep(20);

     }

   } catch (Exception e) {

     // TODO: handle exception

   }

}

正确的代码:

public void run(){

   try {

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

        synchronized(this){

          System.out.println(t.tickets);

            t.tickets--;

            }

        Thread.sleep(20);

     }

   } catch (Exception e) {

     // TODO: handle exception

   }

主要就是把下面的这段代码,

          System.out.println(t.tickets);

            t.tickets--;

使用synchronized方法

synchronized(this){

System.out.println(t.tickets);

            t.tickets--;

            }

其实在这里也用到了锁的原理,一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。这也就避免了两个线程同时去访问共享资源从而使共享资源损坏。

 

在今天的作业中获得了两个小的知识点:

getState()//获取线程状态

Thread.State.TERMINATED//线程.状态.死掉

通过getState()方法获取线程的状态从而和Thread.State.TERMINATED进行对比,如:

if((th1.getState()==Thread.State.TERMINATED) && (th2.getState()==Thread.State.TERMINATED)){

        System.out.println("线程运行完毕");

        break;

     }//如果相等的话则输出“线程运行完毕”并结束这个程序