做网站卖水果哪里进货,nas 可以做网站吗,网站的需求分析都有哪些内容,网站页面链接结构线程的简介
什么是线程
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中#xff0c;是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流#xff0c;一个进程中可以并发多个线程#xff0c;每条线程并行执行不同的任务。
为什么要使用多线…线程的简介
什么是线程
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流一个进程中可以并发多个线程每条线程并行执行不同的任务。
为什么要使用多线程
目前的处理器核心越来越多使用多线程能有更快的响应时间并能有更好的编程模型。
线程优先级
现代操作系统基本采用时分的形式调度运行的线程操作系统分出每一个时间片会根据线程的优先级来分配优先级越高的最先获取执行资源。
在Java线程中通过一个整型成员变量priority来控制优先级优先级的范围从1~10在线程构建的时候可以通过setPriority(int)方法来修改优先级默认优先级是5优先级高的线程分配时间片的数量要多于优先级低的线程。
线程优先级的设置: 频繁阻塞休眠或者I/O操作的线程需要设置 较高优先级偏重计算需要较多CPU时间或者偏运算的线程则设置 较低的优先级确保处理器不会被独占。在不同的 JVM 以及 操作系统 上线程规划会存在差异有些操作系统甚至会忽略对线程优先级的设定。
线程优先级不能作为程序正确性的依赖因为操作系统可以完全不用理会 Java 线程对于优先级的设定。
线程的状态 NEW 初始状态RUNNABLE 运行状态BLOCKED 阻塞状态WAITING 等待状态TIME_WAITING 超时等待状态TERMINATED 终止状态下图是状态变化的介绍
Daemon线程
Daemon 线程是一种支持型线程因为它主要被用作程序中后台调度以及支持性工作。 这意味着当一个Java虚拟机中不存在非Daemon线程的时候Java虚拟机将会退出Daemon线程不一定会执行完。
可以通过调用Thread.setDaemon(true)将线程设置为Daemon线程。需在启动之前设置。
启动和终止线程
线程随着 thread.start() 开始启动 到 run() 方法执行完毕 结束。
我们可以通过 Thread.interrupted() 方法中断线程。 中断可以理解为线程的一个标识位属性它表示一个运行中的线程是否被其他线程进行了中断操作。线程通过检查自身是否被中断来进行响应线程通过方法isInterrupted()来进行判断是否被中断也可以调用静态方法Thread.interrupted()对当前线程的中断标识位进行复位。如果该线程已经处于终结状态即使该线程被中断过在调用该线程对象的isInterrupted()时依旧会返回false。许多声明抛出InterruptedException的方法例如Thread.sleep(long millis)方法这些方法在抛出InterruptedException之前Java虚拟机会先将该线程的中断标识位清除然后抛出InterruptedException此时调用isInterrupted()方法将会返回false。示例
public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {while (true) {try {TimeUnit.SECONDS.sleep(10);System.out.println(time System.currentTimeMillis() / 1000 , i i);} catch (InterruptedException e) {e.printStackTrace();}}}, t1);Thread t2 new Thread(() - {while (true) {i;}}, t2);//设置为 daemon 线程 并启动t1.setDaemon(true);t2.setDaemon(true);t1.start();t2.start();//让t1 t2 运行3sTimeUnit.SECONDS.sleep(3);//中断线程t1.interrupt();t2.interrupt();//获取中断状态System.out.println(time System.currentTimeMillis() / 1000 , t1.isInterrupted() t1.isInterrupted());System.out.println(time System.currentTimeMillis() / 1000 , t2.isInterrupted() t2.isInterrupted());//防止 t1 t2 立即退出TimeUnit.SECONDS.sleep(15);
}
输出
time 1560134045, t1.isInterrupted() false
time 1560134045, t2.isInterrupted() true
java.lang.InterruptedException: sleep interruptedat java.lang.Thread.sleep(Native Method)at java.lang.Thread.sleep(Thread.java:340)at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)at com.tcl.executors.Test.lambda$main$0(Test.java:16)at java.lang.Thread.run(Thread.java:745)
time 1560134055, i -576615207根据输出结果我们知道在线程sleep的时候调用 isInterrupted() 会导致 sleep interrupted 异常并且中断标记也被清除了。
已经被废弃的 suspend()暂停、resume()恢复 和 stop()停止。 废弃原因是在调用方法之后线程不会保证占用的资源被正常释放。
示例
public static void main(String[] args) throws InterruptedException {Thread t new Thread(() - {while (true) {System.out.println(time System.currentTimeMillis() / 1000);try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}});t.setDaemon(true);t.start();TimeUnit.SECONDS.sleep(3);t.suspend();System.out.println(suspend time System.currentTimeMillis() / 1000);TimeUnit.SECONDS.sleep(3);t.resume();System.out.println(resume time System.currentTimeMillis() / 1000);TimeUnit.SECONDS.sleep(3);t.stop();System.out.println(stop time System.currentTimeMillis() / 1000);TimeUnit.SECONDS.sleep(3);
}
输出
time 1560134529
time 1560134530
time 1560134531
suspend time 1560134532
resume time 1560134535
time 1560134535
time 1560134536
time 1560134537
stop time 1560134538线程间通信
volatile和synchronized关键字
volatile修饰的变量程序访问时都需要在共享内存中去读取对它的改变也必须更新共享内存保证了线程对变量访问的可见性。
synchronized对于 同步块 的实现使用了monitorenter和monitorexit指令而 同步方法 则是依靠方法修饰符上的ACC_SYNCHRONIZED来完成的。无论采用哪种方式其本质是对一个对象的监视器monitor进行获取而这个获取过程是排他的也就是同一时刻只能有一个线程获取到由synchronized所保护对象的监视器。
等待/通知机制——wait和notify
指一个线程A调用了对象O的wait()方法进入等待状态而另一个线程B调用了对象O的notify()或者notifyAll()方法线程A收到通知后从对象O的wait()方法返回进而执行后续操作。
等待wait()、wait(long)、wait(long, int)
通知notify()、notifyAll()
示例
private static Object object new Object();public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {try {TimeUnit.SECONDS.sleep(1);synchronized (object) {System.out.println(t1 start object.wait(), time System.currentTimeMillis() / 1000);object.wait();System.out.println(t1 after object.wait(), time System.currentTimeMillis() / 1000);}} catch (InterruptedException e) {e.printStackTrace();}});Thread t2 new Thread(() - {try {TimeUnit.SECONDS.sleep(5);synchronized (object) {System.out.println(t2 start object.notify(), time System.currentTimeMillis() / 1000);object.notify();System.out.println(t2 after object.notify(), time System.currentTimeMillis() / 1000);}synchronized (object) {System.out.println(t2 hold lock again, time System.currentTimeMillis() / 1000);}} catch (InterruptedException e) {e.printStackTrace();}});t1.start();t2.start();
}输出
t1 start object.wait(), time 1560138112
t2 start object.notify(), time 1560138116
t2 after object.notify(), time 1560138116
t2 hold lock again, time 1560138116
t1 after object.wait(), time 15601381161.使用wait()、notify()和notifyAll()时需要先对调用对象加锁,否则会报java.lang.IllegalMonitorStateException异常。
2.调用wait()方法后线程状态由RUNNING变为WAITING并将当前线程放置到对象的等待队列。
3.notify()或notifyAll()方法调用后等待线程依旧不会从wait()返回需要调用notify()或notifAll()的线程释放锁之后等待线程才有机会从wait()返回。
4.notify()方法将等待队列中的一个等待线程从等待队列中移到同步队列中而notifyAll()方法则是将等待队列中所有的线程全部移到同步队列被移动的线程状态由WAITING变为BLOCKED。
5.从wait()方法返回的前提是获得了调用对象的锁。
等待/通知的经典范式
包括 等待方消费者和 通知方生产者。
等待方遵循以下原则 获取对象的锁。如果条件不满足那么调用对象的wait方法被通知后任要检查条件。条件不满足则执行对应的逻辑。示例
synchronized (对象) {while (条件不满足) {对象.wait();}对应的处理逻辑
}
通知方遵循以下原则 获取对象的锁。改变条件。通知所有在等待在对象上的线程。synchronized (对象) {改变条件对象.notifyAll();
}
管道输入/输出流
PipedOutputStream、PipedInputStream、PipedReader 和 PipedWriter。
示例
private static PipedWriter writer;
private static PipedReader reader;public static void main(String[] args) throws InterruptedException, IOException {writer new PipedWriter();reader new PipedReader();//绑定输入输出writer.connect(reader);Thread t new Thread(() - {int res;try {while ((res reader.read()) ! -1) {System.out.print((char) res);}} catch (Exception e) {e.printStackTrace();}});t.start();int res;while ((res System.in.read()) ! -1) {System.out.println(res);writer.write(res);//按回车结束if (res 10) {break;}}writer.close();
}
输出
Hi!
72
105
33
Hi!Thread.join()
thread.join() 即当前线程需要在 thread 线程执行完之后才能继续执行Java Thread.join()详解这里已经做了详细介绍了就不再赘述了。
ThreadLocal
ThreadLocal,即线程变量是一个以ThreadLocal对象为 键 、任意对象 为 值 的存储结构。 这个结构被附带在线程上也就是说一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上的一个值。
可以通过 set(T t) 设置 get() 获取。
示例
private static ThreadLocalString threadLocal new ThreadLocal();public static void main(String[] args) throws InterruptedException {String time String.valueOf(System.currentTimeMillis() / 1000);System.out.println(time time);threadLocal.set(time);Thread t new Thread(() - {String time1 String.valueOf(System.currentTimeMillis());System.out.println(time1 time1);threadLocal.set(time1);});t.start();TimeUnit.SECONDS.sleep(5);System.out.println(threadLocal.get() threadLocal.get());
}
输出
time 1560146178
time1 1560146178263
threadLocal.get() 1560146178可以看到线程t中对threadLocal设置的值并不影响main线程中的值。 set(T value)方法的源代码
可以看到即把 当前ThreadLocal对象 为 key传入的参数 为value 保存在 ThreadLocalMap中。
public void set(T value) {Thread t Thread.currentThread();ThreadLocalMap map getMap(t);if (map ! null)map.set(this, value);elsecreateMap(t, value);
}欢迎大家点赞关注哟