java多线程基础知识(一)

最近在看书,想在这里介绍一下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 :12786382
job priority: 1,count :12719559
job priority: 1,count :12784550
job priority: 1,count :12489459
job priority: 1,count :12499625
job priority: 10,count :13335791
job priority: 10,count :12952607
job priority: 10,count :13257944
job priority: 10,count :12994291
job 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>jps
7744 RemoteMavenServer
12936 AppMain
12428 Jps
12444 Launcher
D:\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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值