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等等!
- java多线程基础知识(一)
- JAVA多线程基础知识(一)
- JAVA多线程基础知识复习一
- java多线程基础知识(一)
- Java 多线程(一) 基础知识与概念
- Java 多线程(一) 基础知识与概念
- Java多线程核心技术(一):基础知识总结
- JAVA多线程编程(一)------基础知识
- Java多线程编程总结笔记——一多线程基础知识
- Java多线程编程总结笔记——一多线程基础知识
- Java多线程(一)进程和线程的基础知识
- Java多线程基础知识
- Java多线程基础知识
- java多线程基础知识
- Java多线程基础知识
- java多线程基础知识1
- Java基础知识:多线程
- Java基础知识:多线程
- View的Touch事件分发简要流程
- 求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字
- Linux Shell编程入门
- MySQL command Line 中命令无效解决
- 练习
- java多线程基础知识(一)
- Altium Designer初试-贴片51系统板
- Codeforces Round #385 (Div. 2) C. Hongcow Builds A Nation 并查集+贪心+组合学、图论、dfs
- App Shortcuts 快捷方式 Android7.1 的"3D Touch"
- 优化MYSchool数据库设计第三章
- JS中全局变量和局部变量
- GD库基础
- 乐观锁和悲观锁
- 自动驾驶全球布局(3)传统汽车厂商