微网站是用什么开发的,线上教学网站,店铺logo图片免费,云南网络推广启动线程的方式
只有#xff1a;
1、X extends Thread;#xff0c;然后X.start
2、X implements Runnable#xff1b;然后交给Thread运行
有争议可以可以查看 Thread源码的注释#xff1a;
There are two ways to create a new thread of execution.Callable的方式需要…启动线程的方式
只有
1、X extends Thread;然后X.start
2、X implements Runnable然后交给Thread运行
有争议可以可以查看 Thread源码的注释
There are two ways to create a new thread of execution.Callable的方式需要塞进FutureTaskFutureTask最终也是继承了Runnable的
线程的状态
Java中线程的状态分为6种 初始(NEW)新创建了一个线程对象但还没有调用start()方法。 运行(RUNNABLE)Java线程中将就绪ready和运行中running两种状态笼统的称为“运行”。 线程对象创建后其他线程(比如main线程调用了该对象的start()方法。该状态的线程位于可运行线程池中等待被线程调度选中获取CPU的使用权此时处于就绪状态ready。就绪状态的线程在获得CPU时间片后变为运行中状态running。 阻塞(BLOCKED)表示线程阻塞于锁。 等待(WAITING)进入该状态的线程需要等待其他线程做出一些特定动作通知或中断。1 超时等待(TIMED_WAITING)该状态不同于WAITING它可以在指定的时间后自行返回。 终止(TERMINATED)表示该线程已经执行完毕。 只有sync才是阻塞状态拿不到锁被迫阻塞 死锁的四个必要条件
1互斥条件指进程对所分配到的资源进行排它性使用即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源则请求者只能等待直至占有资源的进程用毕释放。
2请求和保持条件指进程已经保持至少一个资源但又提出了新的资源请求而该资源已被其它进程占有此时请求进程阻塞但又对自己已获得的其它资源保持不放。
3不剥夺条件指进程已获得的资源在未使用完之前不能被剥夺只能在使用完时由自己释放。
4环路等待条件指在发生死锁时必然存在一个进程——资源的环形链即进程集合{P0P1P2···Pn}中的P0正在等待一个P1占用的资源P1正在等待P2占用的资源……Pn正在等待已被P0占用的资源。
预防死锁
打破互斥条件改造独占性资源为虚拟资源大部分资源已无法改造。
打破不可抢占条件当一进程占有一独占性资源后又申请一独占性资源而无法满足则退出原占有的资源。
打破占有且申请条件采用资源预先分配策略即进程运行前申请全部资源满足则运行不然就等待这样就不会占有且申请。
打破循环等待条件实现资源有序分配策略对所有设备实现分类编号所有进程只能采用按序号递增的形式申请资源。
避免死锁常见的算法有有序资源分配法、银行家算法
解决死锁案例 import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/***类说明演示尝试拿锁解决死锁*/
public class TryLock {private static Lock lock1 new ReentrantLock();//第一个锁private static Lock lock2 new ReentrantLock();//第二个锁//先尝试拿lock1 锁再尝试拿lock2锁lock2锁没拿到连同lock1 锁一起释放掉private static void fisrtToSecond() throws InterruptedException {String threadName Thread.currentThread().getName();Random r new Random();while(true){if(lock1.tryLock()){System.out.println(threadName get lock1);try{if(lock2.tryLock()){try{System.out.println(threadName get lock2);System.out.println(fisrtToSecond do work------------);break;}finally{lock2.unlock();}}}finally {lock1.unlock();}}Thread.sleep(r.nextInt(3));}}//先尝试拿lock2锁再尝试拿lock1锁lock1锁没拿到连同lock2锁一起释放掉private static void SecondToFisrt() throws InterruptedException {String threadName Thread.currentThread().getName();Random r new Random();while(true){if(lock2.tryLock()){System.out.println(threadName get lock2);try{if(lock1.tryLock()){try{System.out.println(threadName get lock1);System.out.println(SecondToFisrt do work------------);break;}finally{lock1.unlock();}}}finally {lock2.unlock();}}Thread.sleep(r.nextInt(3));}}private static class TestThread extends Thread{private String name;public TestThread(String name) {this.name name;}public void run(){Thread.currentThread().setName(name);try {SecondToFisrt();} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {Thread.currentThread().setName(TestDeadLock);TestThread testThread new TestThread(SubTestThread);testThread.start();try {fisrtToSecond();} catch (InterruptedException e) {e.printStackTrace();}}
}
上述案例为啥加了 Thread.sleep(r.nextInt(3));
不加会有活锁问题。加了可以缓解活锁。就是两个线程都在拿锁但是都没拿到拿了很多次才拿到
活锁
两个线程在尝试拿锁的机制中发生多个线程之间互相谦让不断发生同一个线程总是拿到同一把锁在尝试拿另一把锁时因为拿不到而将本来已经持有的锁释放的过程。
解决办法每个线程休眠随机数错开拿锁的时间。
ThreadLocal
与Synchonized的比较
ThreadLocal和Synchonized都用于解决多线程并发訪问。可是ThreadLocal与synchronized有本质的差别。synchronized是利用锁的机制使变量或代码块在某一时该仅仅能被一个线程訪问。而ThreadLocal为每个线程都提供了变量的副本使得每个线程在某一时间訪问到的并非同一个对象这样就隔离了多个线程对数据的数据共享。
如何隔离的数据
每个Thread中都存着一个ThreadLocalMap
ThreadLocal.ThreadLocalMap threadLocals null;查看ThreadLocal的set和createMap函数 public void set(T value) {Thread t Thread.currentThread();ThreadLocalMap map getMap(t);if (map ! null)map.set(this, value);elsecreateMap(t, value);}void createMap(Thread t, T firstValue) {t.threadLocals new ThreadLocalMap(this, firstValue);}上述代码可知当前 Thread和 ThreadLocalMap就绑定在一起了
查看 ThreadLocal的get函数 public T get() {Thread t Thread.currentThread();ThreadLocalMap map getMap(t);if (map ! null) {ThreadLocalMap.Entry e map.getEntry(this);if (e ! null) {SuppressWarnings(unchecked)T result (T)e.value;return result;}}return setInitialValue();}通过get可以看到 getMap获取的是当前Thread的 ThreadLocalMap也就跟其他线程无关了 ThreadLocalMap里面有 Entry就是用来存放数据的
static class Entry extends WeakReferenceThreadLocal? {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal? k, Object v) {super(k);value v;}
}为什么不直接搞个Map存一下数据 import java.util.HashMap;
import java.util.Map;/*** 类说明自己实现的ThreadLocal*/
public class MyThreadLocalT {/*存放变量副本的map容器以Thread为键变量副本为value*/private MapThread,T threadTMap new HashMap();public synchronized T get(){return threadTMap.get(Thread.currentThread());}public synchronized void set(T t){threadTMap.put(Thread.currentThread(),t);}}
直接用一个Map虽然可以隔离但是压力都给到了Map上在多线程时对这个Map会有激烈的竞争