集成Thread类
public class Thread01 extends Thread{
@Override
public void run(){
System.out.println("我是子线程");
System.out.println("子线程 = "+Thread.currentThread().getName());
}
public static void main(String[] args){
System.out.println("main = "+Thread.currentThread().getName());
//
}
}
实现Runnable接口
public class TheadTest02 implements Runnable{
System.out.println("main = "+Thread.currentThread().getName());
new Thread(new ThreadTest02(),"test-01").start();
}
@Override
public void run(){
System.out.println("子线程 = "+Thread.currentThread().getName());
}
}
使用lambda表达式
public class TheadTest02 implements Runnable{
public static void main(String[] args){
System.out.println("main = "+Thread.currentThread().getName());
new Thread(()->{
System.out.println("子线程 = "+Thread.currentThread().getName());
});
}
}
使用Callable,FutureTask实现
此种方式能获取到线程的返回结果。
使用线程池创建线程
public class ThreadTest03{
public static void main(String[] args){
System.out.println("main = "+Thread.currentThread().getName());
ExecutorService exP = Executors.newFixedThreadPool(2);/*可变定长线程池*/
ExecutorService exS = Executors.newCachedThreadPool();
exS.execute(new Runnable(){
@Override
public void run(){
System.out.println("子线程 "+Thread.currentThread().getName());
}
});
}
}
使用Spring的注解方式@Sync
自定义异步注解实现方法
Aop拦截只要在我们的方法上有使用到@WindakaAsync就单独的开启一个异步线程执行我们的目标方法。
Aop环绕通知@Around会拦截目标方法
线程安全性问题
多个线程同时对一个全局变量做写的操作,可能会受到其它线程的干扰,就会发生线程安全问题。
public class ThreadCount implements Runnable{ private int count = 100; @Override public void run(){ count--; System.out.println("-->count = "+count+" , “+Thread.currentThread().getName()); } } public class Thread03 { public static void main(String[] args){ ThreadCount thC = new ThreadCount(); new Thread(thC).start(); new Thread(thC).start(); } }
如何解决线程多线程线程安全问题?也就是如何实现线程同步?
核心思想:上锁
可能会发生线程安全性问题的代码需要上锁。
public class ThreadCount implements Runnable{ private int count = 100; @Override public void run(){ /*此处需上锁*/ synchronized(this){ count--; } /*此处需解锁*/ System.out.println("-->count = "+count+" , “+Thread.currentThread().getName()); } }
Synchronized锁的基本用法
修饰代码块
修饰实例方法
如果Synchronized加到实例方法上,则使用this锁。
如果Synchronized加到静态方法上,则使用 synchronized(当前的类名.class){ xx }
修饰静态方法
synchronized死锁诊断工具
jconsole.exe
Sping bean对象是单例模式
@Scope(value = "prototype") /*如果把bean对象设置成原型,bean对象就变成多例模式*/
public class CountService{
}
wait(),notify()使用
public class ThreadTest{
class Res{
public String userName;
public String sex;
public boolean flag = false;
}
class InPutThread extend Thread{
public Res res;
public InPutThread(Res res){
this.res = res;
}
@Override
public void run(){
int count = 0;
while(true){
synchronized(res){
if(res.flag == true){
res.wait();
}
if(count == 0){
res.userName = "小强";
res.sex = "男";
}else{
res.userName = "小花";
res.sex = "女";
}
res.flag = true;
res.notify();
}
}
}
}
class OutPutThread extends Thread{
private Res res;
public OutPutThread(Res res){
this.res = res;
}
@Override
public void run(){
while(true){
synchronized(res){
if(res.flag == flase){
res.wait();
}
System.out.println(res.userName+" , "+res.sex);
res.flag = flase;
res.notify();
}
}
}
}
public static void main(String[] args){
new ThreadTest().print();
}
public void print(){
Res res = new Res();
InPutThread in = new InPutThread(res);
OutPutThread out = new OutPutThread(res);
in.start();
out.start();
}
}
Lock锁
Synchronized不需要手动释放锁,lock锁需要进行手动释放锁。因此必须xx.lock()和xx.unlock()配对使用。
LogManager练习
@Component
public class LogManager{
private BlockingQueue<String> bQ = new LinkedBlockingDeque<>();
public LogManager(){
LogThread lT = new LogThread();
lT.start();
}
public void info(String log){
bQ.offer(log);
}
class LogThread extends Thread{
@Override
public void run(){
while(true){
String log = bQ.poll();
if(log != null){
System.out.println(log);
}
}
}
}
}