共计 5578 个字符,预计需要花费 14 分钟才能阅读完成。
前言
过程是计算机中程序对于某几何数据汇合上的一次运行流动,是零碎进行资源分配和调度的根本单位。是操作系统构造的根底
线程能够说是轻量级的过程,是程序执行的最小单位,应用多线程而不必多过程去进行并发程序的设计,是因为线程之间的切换与调度的老本远小于过程。
线程的几种状态
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();}
}
<<<
2
group1===Thread-0
java.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 相干技术文章或行业资讯,欢送大家关注和转发文章!