前言
过程是计算机中程序对于某几何数据汇合上的一次运行流动,是零碎进行资源分配和调度的根本单位。是操作系统构造的根底
线程能够说是轻量级的过程,是程序执行的最小单位,应用多线程而不必多过程去进行并发程序的设计,是因为线程之间的切换与调度的老本远小于过程。
线程的几种状态
New状态示意刚刚创立的线程,这种线程还没有开始执行RUNNABLE:当线程创立好之后,调用线程的start办法就会进入就绪状态。BLOCKED:当线程运行过程如果遇到了Syschronized就会进入阻塞状态。TIMED_WATING:示意期待状态,有工夫限度的(sleep)WAITING:示意进入一个无工夫显示的期待状态(wait)TERMINATED:示意完结状态。
线程的基本操作
新建线程
实现Runable接口或者new Thread
终止线程
为什么不倡议应用stop?
因为stop办法比拟暴力,强行把执行的程序终止,可能会引发数据不统一的问题,Thread.stop()
办法在完结线程时,会间接终止线程,并立刻开释这个线程的所持有的锁。比方数据写到一半,强行终止掉了,数据就会被毁坏。
线程中断
interrupt() //中断线程。相当于设置中断标记位isInterrypted() //判断是否被中断interrupted() //判断是都被中断,并革除以后的中断状态
Thread.sleep()
办法因为中断而抛出异样,此时它会革除中断标记,如果不加解决,那么下一次循环开始时,就无奈捕捉这个异样,能够再次设置中断标记来不便循环判断。
期待和告诉
当在一个对象实力上条用wait()
办法之后。以后线程就会在这个对象上期待。在线程A中调用了obj.wait()
办法,那么变成A就会进行继续执行,转为期待状态,直到其余线程调用了obj.notify()
办法才有机会继续执行(并不是肯定)
如果一个线程调用了obj.wait()
那么它就会进入这个object的期待队列,这个期待队列可能会有多个线程,因为零碎运行多个线程同时期待某一个对象,当obj.notify()
办法被调用时,就会随机抉择一个线程,将其唤醒,这个唤醒是齐全随机的。
notifyAll()
办法的性能是唤醒所有在该对象期待队列中期待的线程。
守护线程的finally不肯定会执行。如果除守护线程外的所有线程都完结了,那么守护线程就立刻退出没有执行finally代码块的机会。
挂起(suspend)和持续(resume)执行
不举荐执行suspend(),因为该办法在导致线程暂停的同时,并不会开释任何资源。影响其余想要拜访该资源的线程,直到以后线程应用resume
操作,是以后线程继续执行,然而此处有一个隐患。如果resume在suspend之前运行了,那么被挂起的线程将不能继续执行上来。
public class BadSuspend { public static Object u = new Object(); static ChangeObjectThread t1 = new ChangeObjectThread("t1"); static ChangeObjectThread t2 = new ChangeObjectThread("t2"); public static class ChangeObjectThread extends Thread { public ChangeObjectThread(String name){ super.setName(name); } @Override public void run() { synchronized (u) { System.out.println("in "+getName()); Thread.currentThread().suspend(); } } } public static void main(String[] args) throws InterruptedException { t1.start(); Thread.sleep(100); t2.start(); t1.resume(); t2.resume();//无奈直到这一行先执行,还是Thread.currentThread().suspend();先执行 t1.join(); t2.join(); }}
期待线程完结(join)和谦让(yeild)
public final synchronized void join(long millis) throws InterruptedException//有最大期待时长的期待public final synchronized void join(long millis, int nanos)throws InterruptedException//毫秒,加纳秒级别的期待public final void join() throws InterruptedException//示意无限期的期待
package com.atmb.me;public class joinAndYeild { public volatile static int i =0; public static class myThread implements Runnable{ @Override public void run() { for (int j = 0; j < 1000000; j++) { i+=1; } } } public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new myThread()); thread.start(); thread.join();//期待thread线程执行完结 System.out.println(i);//后果为1000000 }}
public static native void yield();
这个办法一旦执行,就会使以后线程让出cpu,让出cpu之后,该线程会持续进行cpu资源的抢夺,之后持续失常运行。
线程组
package com.atmb.me;public class ThreadGroupTest implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getThreadGroup().getName()+"==="+Thread.currentThread().getName()); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { ThreadGroup group1 = new ThreadGroup("group1"); Thread thread1 = new Thread(group1, new ThreadGroupTest()); Thread thread2 = new Thread(group1, new ThreadGroupTest()); thread1.start(); thread2.start(); System.out.println(group1.activeCount());//沉闷线程数 group1.list(); }}<<<2group1===Thread-0java.lang.ThreadGroup[name=group1,maxpri=10]group1===Thread-1 Thread[Thread-0,5,group1] Thread[Thread-1,5,group1]
守护线程(Daemon)
守护线程要守护的对象曾经不存在了,那么整个应用程序就应该技术,因而当java利用内只有守护线程时,java虚拟机就会天然退出。
package geym.ch2;public class DaemonDemo { public static class DaemonT extends Thread{ public void run(){ while(true){ System.out.println("I am alive"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws InterruptedException { Thread t=new DaemonT(); t.setDaemon(true); t.start();// Thread.sleep(2000); }}
设置守护线程,必须要在start之前设置,否则会失去异样信息。
线程优先级
Java中的线程能够有本人的优先级。优先级高的线程在竞争资源时,会更有劣势,更大概率抢占到资源,java中线程优先级能够设置为1-10.
其中有三个动态标量标识三个对应的优先级。
/** * 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;
public class PriorityDemo { public static class HightPriority extends Thread{ static int count=0; public void run(){ while(true){ synchronized(PriorityDemo.class){ count++; if(count>10000000){ System.out.println("HightPriority is complete"); break; } } } } } public static class LowPriority extends Thread{ static int count=0; public void run(){ while(true){ synchronized(PriorityDemo.class){ count++; if(count>10000000){ System.out.println("LowPriority is complete"); break; } } } } } public static void main(String[] args) throws InterruptedException { Thread high=new HightPriority(); LowPriority low=new LowPriority(); high.setPriority(Thread.MIN_PRIORITY); low.setPriority(Thread.MAX_PRIORITY); low.start(); high.start(); }}
线程平安与关键字synchronized
synchronized
- 指定加锁对象,对给定的对象进行加锁,
- 用于实例办法,对以后的实例进行加锁
- 用于静态方法,对以后类进行加锁
谬误的加锁
package com.atmb.me;public class lockError implements Runnable { public static Integer i =0; public static lockError instance = new lockError(); public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(instance); Thread thread2 = new Thread(instance); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println(i); } @Override public void run() { for (int j = 0; j < 100000; j++) { synchronized (i){ i+=1; } } }}<<<142957
起因在于Integer类型属于不可变对象,一旦创立就不可能被扭转,当integer对象赋值为新值时,以后援用指向的对象就扭转了。
指令重排的前提
指令重排须要保障串行语义的一致性,指令重排不会使串行的语义逻辑产生问题。
指令重排的目标?
为了缩小中断流水线
那些指令不能重排
- 程序程序准则,一个线程内保障语义的串行性
- volatile规定:volatile变量的写先与读产生,宝整顿volatile变量的可见性
- 传递性:解锁必然产生在随后的加锁前
- 线程的
start()
办法先于它的动作 - 线程的所有操作先于线程的终结(interrupt)
- 线程的中断(
interrupt()
)先于被中断线程的代码 - 对象的构造函数的执行,完结先于
finalize()
的办法
是否会开释锁
- yield让出cpu执行权,不会开释锁
- sleep休眠时,不会开释锁
- 调用wait办法之后,会开释锁,唤醒之后,会再次竞争锁,而后执行wait()办法后的代码
- nofify nodifyall 对锁没有影响,个别放同步代码块的最初一行
最初
感激你看到这里,看完有什么的不懂的能够在评论区问我,感觉文章对你有帮忙的话记得给我点个赞,每天都会分享java相干技术文章或行业资讯,欢送大家关注和转发文章!