java多线程基础知识(一)

来源:互联网 发布:淘宝怎么秒杀抢东西 编辑:程序博客网 时间:2024/06/05 09:33

最近在看书,想在这里介绍一下java多线程的一些知识,加深记忆,分享成果…

直奔主题…

线程优先级

目前操作系统采用时分的形式来调度线程,操作系统会分出一个一个时间片,线程会分配到若干时间片,当线程用完这个时间片就会发生线程调度,等待下一次分配.线程被分配的时间片越多,此线程就获得资源越多,而线程优先级就决定了此线程被分配的时间片多少!
java线程中,通过成员变量priority控制优先级.优先级范围从1-10,线程初始化时,通过setPriority来设置线程优先级(默认是5).下面代码示例:

/** * 线程的优先级 * Created by gzd on 2017/1/10. */public class Priority {    private static volatile boolean notStart = Boolean.TRUE;    private static volatile boolean notEnd = Boolean.TRUE;    public static void main(String[] args) throws InterruptedException {        ArrayList<Job> jobs = new ArrayList<>();        for (int i = 0; i < 10; i++) {            int priority = i < 5 ? Thread.MIN_PRIORITY : Thread.MAX_PRIORITY;            Job job = new Job(priority);            jobs.add(job);            Thread thread = new Thread(job, "线程: " + i);            thread.setPriority(priority);            thread.start();        }        notStart = Boolean.FALSE;        TimeUnit.SECONDS.sleep(10);        notEnd = Boolean.FALSE;        for (Job job : jobs){            System.out.println("job priority: "+job.priority + ",count :"+job.jobCount);        }    }    private static class Job implements Runnable {        private int priority;        private long jobCount;        public Job(int priority) {            this.priority = priority;        }        @Override        public void run() {            while (notStart) {                Thread.yield();            }            while (notEnd) {                Thread.yield();                jobCount++;            }        }    }}

程序运行结果是:

job priority: 1,count :12786382job priority: 1,count :12719559job priority: 1,count :12784550job priority: 1,count :12489459job priority: 1,count :12499625job priority: 10,count :13335791job priority: 10,count :12952607job priority: 10,count :13257944job priority: 10,count :12994291job priority: 10,count :13351521

可以看到,线程优先级,并没有起到绝对性的作用,这就说明,不能依靠线程的优先级来保证程序结果,因为操作系统不需要理会它.

线程的状态

java线程的生命周期一共有6种状态.分别为:

  • NEW 初始状态,线程已经创建,但是还没有执行start方法
  • RUNNABLE 运行状态,就绪和运行状态的统称
  • BLOCKED 阻塞状态,阻塞于锁
  • WAITING 等待状态
  • TIME_WAITING 超时等待,区别于上一个状态,他可以在制定的时间自行返回
  • TERMINATED 终止状态,线程执行结束

下面给出一段示例代码:

/** * 线程状态 * Created by gzd on 2017/1/10. */public class ThreadState {    //这个线程一直睡眠    private static Runnable timeWaiting = () -> {        while (true) {            try {                TimeUnit.SECONDS.sleep(100);            } catch (InterruptedException e) {            }        }    };    //这个线程一直在当前类实例上等待    private static Runnable waiting = () -> {        while (true) {            synchronized (ThreadState.class) {                try {                    ThreadState.class.wait();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    };    //这个演示block    private static Runnable block = () -> {      synchronized (Priority.class){          while (true){              try {                  TimeUnit.SECONDS.sleep(100);              } catch (InterruptedException e) {                  e.printStackTrace();              }          }      }    };    public static void main(String[] args) {        new Thread(timeWaiting, "timeWaiting").start();        new Thread(waiting, "waiting").start();        new Thread(block,"block-1").start();        new Thread(block,"block-2").start();    }}

利用jstack工具来查看线程的状态:

D:\workspace\study>jps7744 RemoteMavenServer12936 AppMain12428 Jps12444 LauncherD:\workspace\study>jstack 12936"block-2" #15 prio=5 os_prio=0 tid=0x0000000019dc1000 nid=0x2cdc waiting on condition [0x000000001b38e000]   java.lang.Thread.State: TIMED_WAITING (sleeping)"block-1" #14 prio=5 os_prio=0 tid=0x0000000019dbf000 nid=0x2d04 waiting for monitor entry [0x000000001b28e000]   java.lang.Thread.State: BLOCKED (on object monitor)"waiting" #13 prio=5 os_prio=0 tid=0x0000000019dbe800 nid=0x3028 in Object.wait() [0x000000001b18f000]   java.lang.Thread.State: WAITING (on object monitor)"timeWaiting" #12 prio=5 os_prio=0 tid=0x0000000019dbd800 nid=0x192c waiting on condition [0x000000001b08e000]   java.lang.Thread.State: TIMED_WAITING (sleeping)

为了节省篇幅,已经删除掉其他没用的打印结果,可以看到:

  • waiting线程是在WAITING ,没有一个确切的时间.
  • timeWaiting线程因为使用了sleep,所以,是TIMED_WAITING 状态,等待一个确切的时间后启动线程.
  • block-2”因为获得了Priority.class的锁所以状态为TIMED_WAITING.
  • block-1因为block-2正在占用锁,所以他没有获取到锁,所以它的状态为BLOCKED.

关于jstack的使用:可以在命令行内直接输入jstack,也可以去文件夹内双击启动(windows),具体可以谷歌一下

线程状态的变化可以用以下UML图来说明:
这里写图片描述

注意:java是讲运行和就绪合并成RUNNABLE状态,阻塞在synchronized的为阻塞状态,但是阻塞在java.concurrent包中Lock接口的状态却是扥带状态,因为其对于阻塞的实现使用的时LockSupport类的方法.

Daemon线程

Daemon线程为支持型线程,具体作用为程序中后台调度以及支持工作.其实可以理解为,如果目前只有Daemon线程,那么JVM可以停止工作退出.

可以通过Thread.setDaemon(true)讲线程设置为Daemon线程

设置方法:

/** * Created by gzd on 2017/1/10. * 怎么样设置Daemon线程 */public class Daemon {    private static Runnable daemonRunner = () -> {        try {            System.out.println("========begin============");            TimeUnit.SECONDS.sleep(5);            System.out.println("========end============");        } catch (InterruptedException e) {            e.printStackTrace();        } finally {            System.out.println("========finally============");        }    };    public static void main(String[] args) {        Thread daemonThread = new Thread(daemonRunner, "daemonThread");        daemonThread.setDaemon(Boolean.TRUE);        daemonThread.start();    }}

运行程序之后可以发现,没有任何打印结果,因为main方法中,启动了daemonThread线程之后就没有其他操作而终止.也没有其他需要执行的线程,所以JVM执行退出,finally块儿里面的也不会执行.当我们想要做一些主要程序以外的其他工作时,可以用此线程来完成.

这篇就先到这里,下一篇会继续介绍线程的启动/停止,线程间通讯,join等等!

0 0
原创粉丝点击