源无极

导航

 

一、线程可以暂停意味着可以恢复

暂停用suspend(),resume()恢复线程。

package com.it.po.thread03;

public class MyThread01 extends Thread {
    private long i=0;

    public long getI() {
        return i;
    }

    public void setI(long i) {
        this.i = i;
    }

    @Override
    public void run() {
        while (true){
            i++;
        }
    }
}

 

package com.it.po.thread03;


import com.it.po.thread02.MyThread02;

import javax.swing.*;

public class Run01 {
    public static void main(String[] args){
        try {
            MyThread01 my = new MyThread01();
            my.start();
            Thread.sleep(500);
            my.suspend();//暂停
            System.out.println("第一次获取i= "+my.getI()+" 时间点:"+System.currentTimeMillis());
            Thread.sleep(500);
            System.out.println("暂停后获取i= "+my.getI()+" 时间点:"+System.currentTimeMillis());
            my.resume();//恢复
            Thread.sleep(500);
            my.suspend();//再次暂停
            System.out.println("恢复暂停后获取i= "+my.getI()+" 时间点:"+System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

 

 

 

 线程停止状态

 

 (一)、suspend(),resume()方法的缺点-------独占

       使用这两个方法,如果使用不当,极容易造成公共的同步对象的独占,使得其他线程

无法访问公共同步对象。

 

package com.it.po.thread03;

public class SynchronizedObject {
    synchronized public  void printString(){
       System.out.println("线程 "+Thread.currentThread().getName()+" 进入printString方法...");
          if("a".equals(Thread.currentThread().getName())){
              System.out.println("a线程永远暂停了...");
              Thread.currentThread().suspend();
          }
          System.out.println("线程 "+Thread.currentThread().getName()+" 从printString方法出去...");
    }
}

 

 

package com.it.po.thread03;

public class SysObjRun {
    public static void main(String[] args){
        try {
            SynchronizedObject object = new SynchronizedObject();
            //线程a
            Thread t1 = new Thread() {
                @Override
                public void run() {
                    super.run();
                    object.printString();
                }
            };
            t1.setName("a");
            t1.start();
            Thread.sleep(1000);
            //线程b
            Thread t2 = new Thread() {
                @Override
                public void run() {
                    super.run();
                    object.printString();
                }
            };
            t2.setName("b");
            t2.start();
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

 

 

 

 

 

 暂停在这里,b线程永远进不去

变式1 去掉   synchronized

 

package com.it.po.thread03;

public class SynchronizedObject {
     public  void printString(){
       System.out.println("线程 "+Thread.currentThread().getName()+" 进入printString方法...");
          if("a".equals(Thread.currentThread().getName())){
              System.out.println("a线程永远暂停了...");
              Thread.currentThread().suspend();
          }
          System.out.println("线程 "+Thread.currentThread().getName()+" 从printString方法出去...");
    }
}

 

线程 a 进入printString方法...
a线程永远暂停了...
线程 b 进入printString方法...
线程 b 从printString方法出去...

 

a线程一直停着。

(二)、第二种独占锁

package com.it.po.thread03;

public class MyThread02 extends Thread {
    private long i=0;
    @Override
    public void run() {
        while (true){
            i++;
            System.out.println("i= "+i);
        }
    }
}
package com.it.po.thread03;


public class Run02 {
    public static void main(String[] args){
        try {
            MyThread02 my = new MyThread02();
            my.start();
            Thread.sleep(300);
            my.suspend(); 
            System.out.println("main end。。。");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

 

 

 

 

 

分析:

当程序运行到println()方法内部时,同步锁未被释放,导致println()一直处于暂停状态

 

 虽然suspend()作废了,但是研究它是有意义的。

(三)、suspend和resume方法的缺点----不同步

使用这两个方法,很容易出现因为行程暂停而数据不同步的情况。

package com.it.po.thread03;

public class MyObject {
    private String username="1";
    private String password="11";
    public void setValue(String u,String p){
        this.username=u;
        if("a".equals(Thread.currentThread().getName())){
            System.out.println("a线程暂停了。。。");
            Thread.currentThread().suspend();
        }
        this.password=p;
    }

    public void printUsernameAndPassword(){
        System.out.println("用户:"+username+" 密码 "+password);
    }

}

 

 

package com.it.po.thread03;

public class MyObjRun {
    public static void main(String[] args){
        try {
            MyObject my = new MyObject();
            //线程a
            Thread t1 = new Thread() {
                @Override
                public void run() {
                    super.run();
                    my.setValue("a","aa");
                }
            };
            t1.setName("a");
            t1.start();
            Thread.sleep(1000);
            //线程b
            Thread t2 = new Thread() {
                @Override
                public void run() {
                    super.run();
                  my.printUsernameAndPassword();
                }
            };
            t2.setName("b");
            t2.start();
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

 

 

 

 

 二、yield方法

该方法的作用是放弃当前CPU资源,将它让给其他的任务去占用CPU时间,但是放弃的时间不确定

可能刚刚放弃,又马上获得CPU时间片

package com.it.po.thread03;

public class MyThread03 extends Thread {
    @Override
    public void run() {
        long begin = System.currentTimeMillis();
        int count=0;
        for(int i=0;i<5000000;i++){
         //   Thread.yield();
        count=count+(i+1);
        }
        long end = System.currentTimeMillis();
        System.out.println("用时: "+(end-begin));
    }
}

 

package com.it.po.thread03;
public class Run03 {
    public static void main(String[] args){
        MyThread03 my = new MyThread03();
        my.start();
    }
}

 

 

用时: 9

 

 去掉注释符号再次执行

用时: 3596

 

 注意:这个3596时间是不确定的,可以多执行几次对比

 

三、线程的优先级

      操作系统中线程可以划分优先级,优先级较高的线程得到CPU资源较多,也就是CPU优先执行,

优先级比较高的线程对象中的任务。

    设置优先级有助于帮助 “线程规划器”确定下一次选择哪一个线程来优先执行。

设置线程的优先级用setPriority()方法。

此方法源码如下

 /**
     * Changes the priority of this thread.
     * <p>
     * First the <code>checkAccess</code> method of this thread is called
     * with no arguments. This may result in throwing a
     * <code>SecurityException</code>.
     * <p>
     * Otherwise, the priority of this thread is set to the smaller of
     * the specified <code>newPriority</code> and the maximum permitted
     * priority of the thread's thread group.
     *
     * @param newPriority priority to set this thread to
     * @exception  IllegalArgumentException  If the priority is not in the
     *               range <code>MIN_PRIORITY</code> to
     *               <code>MAX_PRIORITY</code>.
     * @exception  SecurityException  if the current thread cannot modify
     *               this thread.
     * @see        #getPriority
     * @see        #checkAccess()
     * @see        #getThreadGroup()
     * @see        #MAX_PRIORITY
     * @see        #MIN_PRIORITY
     * @see        ThreadGroup#getMaxPriority()
     */
    public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }

 

 线程优先级分为1~10级,小于1或是大于10则jdk抛出异常

JDK使用3个常量来预置定义优先级的值。

 /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;

 

 (一)、优先级具有继承特性

优先级具有继承性,比如A线程启动B线程,则B线程和A线程的优先级 一样

package com.it.po.thread03;
public class MyThread04_1 extends Thread {
    @Override
    public void run() {
        System.out.println("MyThread04_1: priority= "+this.getPriority());
        new MyThread04_2().start();
    }
}

 

package com.it.po.thread03;

public class MyThread04_2 extends Thread {
    @Override
    public void run() {
     System.out.println("MyThread04_2:priority= "+this.
package com.it.po.thread03;
public class Run04 {
    public static void main(String[] args){
      System.out.println("main1 priority= "+Thread.currentThread().getPriority());
      //Thread.currentThread().setPriority(8);
        System.out.println("main2 priority= "+Thread.currentThread().getPriority());
        MyThread04_1 my = new MyThread04_1();
        my.start();
    }
}

 

getPriority());
    }
}

 

main1 priority= 5
main2 priority= 5
MyThread04_1: priority= 5
MyThread04_2:priority= 5

 

放开注释

main1 priority= 5
main2 priority= 8
MyThread04_1: priority= 8
MyThread04_2:priority= 8

 

(二)、优先级具有规则性

下面看优先级设置后带来的效果

package com.it.po.thread03;

import java.util.Random;

public class MyThread05_1 extends Thread {
    @Override
    public void run() {
        long begin = System.currentTimeMillis();
        long addResult=0;
        for(int j=0;j<100;j++){
          for(int i=0;i<5000;i++){
              Random random = new Random();
              random.nextInt();
              addResult=addResult+i;
          }
        }
        long end = System.currentTimeMillis();
        System.out.println("**********线程1用时 time= "+(end-begin)+" 毫秒");
    }
}

 

package com.it.po.thread03;

import java.util.Random;

public class MyThread05_2 extends Thread {
    @Override
    public void run() {
        long begin = System.currentTimeMillis();
        long addResult=0;
        for(int j=0;j<100;j++){
          for(int i=0;i<5000;i++){
              Random random = new Random();
              random.nextInt();
              addResult=addResult+i;
          }
        }
        long end = System.currentTimeMillis();
        System.out.println("**********线程2用时 time= "+(end-begin)+" 毫秒");
    }
}

 

package com.it.po.thread03;


import java.util.Random;

public class Run05 {
    public static void main(String[] args){
        for(int i=0;i<5;i++) {
            MyThread05_1 my1 = new MyThread05_1();
            my1.setPriority(10);
            my1.start();
            MyThread05_2 my2 = new MyThread05_2();
            my2.setPriority(1);
            my2.start();
        }
    }
}

 

**********线程1用时 time= 793 毫秒
**********线程1用时 time= 1056 毫秒
**********线程2用时 time= 936 毫秒
**********线程1用时 time= 1119 毫秒
**********线程1用时 time= 1288 毫秒
**********线程1用时 time= 1486 毫秒
**********线程2用时 time= 1581 毫秒
**********线程2用时 time= 1712 毫秒
**********线程2用时 time= 1919 毫秒
**********线程2用时 time= 1614 毫秒

 

       优先级高的总是大部分先执行,但是不代表优先级高的先全部执行完。

CPU尽量将优先级高的线程先执行。

 

 (三)、优先级具有随机性

其实优先级高的不一定先执行。优先级是具有随机性的。

package com.it.po.thread03;

import java.util.Random;

public class MyThread06_1 extends Thread {
    @Override
    public void run() {
        long begin = System.currentTimeMillis();
          for(int i=0;i<2000;i++){
              Random random = new Random();
              random.nextInt();
          }
        long end = System.currentTimeMillis();
        System.out.println("**********线程1用时 time= "+(end-begin)+" 毫秒");
    }
}

 

 

package com.it.po.thread03;

import java.util.Random;

public class MyThread06_2 extends Thread {
    @Override
    public void run() {
        long begin = System.currentTimeMillis();
          for(int i=0;i<2000;i++){
              Random random = new Random();
              random.nextInt();
          }
        long end = System.currentTimeMillis();
        System.out.println("**********线程2用时 time= "+(end-begin)+" 毫秒");
    }
}
package com.it.po.thread03;


public class Run06 {
    public static void main(String[] args){
        for(int i=0;i<5;i++) {
            MyThread06_1 my1 = new MyThread06_1();
            my1.setPriority(5);
            my1.start();
            MyThread06_2 my2 = new MyThread06_2();
            my2.setPriority(6);
            my2.start();
        }
    }
}

 

 

**********线程2用时 time= 0 毫秒
**********线程1用时 time= 2 毫秒
**********线程1用时 time= 1 毫秒 **********线程2用时 time= 0 毫秒
**********线程2用时 time= 1 毫秒 **********线程2用时 time= 0 毫秒
**********线程2用时 time= 13 毫秒 **********线程1用时 time= 11 毫秒
**********线程1用时 time= 16 毫秒 **********线程1用时 time= 0 毫秒

 

 优先级与打印的顺序无关

(四)、谁算的快

 

package com.it.po.thread03;

public class ThreadA  extends Thread{
private int count=0;
    public int getCount() {
        return count;
    }
    @Override
    public void run() {
        super.run();
        while (true){
            count++;
        }
    }
}

 

package com.it.po.thread03;

public class ThreadB extends Thread{
private int count=0;
    public int getCount() {
        return count;
    }
    @Override
    public void run() {
        super.run();
        while (true){
            count++;
        }
    }
}
package com.it.po.thread03;


public class RunAB {
    public static void main(String[] args){
        try {
            ThreadA a = new ThreadA();
            a.setPriority(Thread.NORM_PRIORITY-2);//优先级3
            a.start();
            ThreadB b = new ThreadB();
            b.setPriority(Thread.NORM_PRIORITY+2);//优先级7
            b.start();
            Thread.sleep(6000);
            a.stop();
            b.stop();
            System.out.println("timeA= "+a.getCount());
            System.out.println("timeB= "+b.getCount());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

 

timeA= 1452546210
timeB= 1473208109

 

优先级一样的话

package com.it.po.thread03;


public class RunAB {
    public static void main(String[] args){
        try {
            ThreadA a = new ThreadA();
            a.setPriority(Thread.NORM_PRIORITY);//优先级5
            a.start();
            ThreadB b = new ThreadB();
            b.setPriority(Thread.NORM_PRIORITY);//先级5
            b.start();
            Thread.sleep(6000);
            a.stop();
            b.stop();
            System.out.println("timeA= "+a.getCount());
            System.out.println("timeB= "+b.getCount());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

 

timeA= 1498458754
timeB= 1499677846

 

四、守护线程

java有两种线程,一种是用户线程,另一种是守护线程

守护线程:

      是一种特殊线程,含有陪伴的含义,当进程中不含守护线程了,则守护线程自动销毁。

典型的守护线程就是垃圾回收线程。任何一个守护线程都是JVM中的所有非守护线程的保姆,

只要当前JVM中存在非守护线程,且没有结束,守护线程就要工作,只有当JVM中最后一个非守护线程结束了

守护线程随着JVM一同结束,守护线程的作用就是为其他线程提供便利。

package com.it.po.thread03;

public class MyThread07 extends Thread {
    private long i=0;
    @Override
    public void run() {
        while (true){
            try {
                i++;
                System.out.println("i= "+i);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

 

package com.it.po.thread03;


public class Run07 {
    public static void main(String[] args){
        try {
            MyThread07 my = new MyThread07();
            my.setDaemon(true);//设置为守护线程
            my.start();
            Thread.sleep(6000);
            System.out.println("my是守护线程 ,main执行到此,my线程将也结束。。。");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

 

 

 

 

 

 

 

 

 

 

posted on 2019-11-10 20:21  源无极  阅读(152)  评论(0)    收藏  举报