多线程
-
多线程可以减少业务执行时间,最大化处理器资源利用率
-
多线程必然涉及到线程不安全,比如抢票,所以就要用到synchronized
-
线程开启不一定立即执行,由CPU调度执行顺序
-
创建线程最常用方法如下:
//实现Runnable接口,重写run()方法 //创建线程对象,执行线程需要丢入runnable接口实现类,调用start()方法 public class ThreadTest1 implements Runnable { @Override public void run() { //run方法线程体 for (int i = 0; i < 20 ; i++) { System.out.println("run方法"); } } public static void main(String[] args) { //创建Runnable接口的实现对象 ThreadTest1 thread = new ThreadTest1(); //创建线程对象,通过线程对象来开始我们的线程,代理 new Thread(thread).start(); for (int i = 0; i < 20; i++) { System.out.println("main方法"); } } }
-
龟兔赛跑:
//龟兔赛跑 public class ThreadTest3 implements Runnable { //胜利者 private static String winner; @Override public void run() { for (int i = 0; i <= 100; i++) { //模拟兔子休息2毫秒 if (Thread.currentThread().getName().equals("兔子")&& i%10==0){ try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } //判断比赛是否结束 boolean flag = over(i); //如果比赛结束,就停止程序 if (flag){ break; } System.out.println(Thread.currentThread().getName()+"---->跑了" + i + "步"); } } //判断是否完成比赛 private boolean over(int buShu) { //判断是否有胜利者 if (winner != null) {//已经存在胜利者 return true; } if (buShu >= 100){ winner = Thread.currentThread().getName(); System.out.println("winner is "+winner); return true; } return false; } public static void main(String[] args) { ThreadTest3 threadTest3 = new ThreadTest3(); new Thread(threadTest3,"兔子").start(); new Thread(threadTest3,"乌龟").start(); } }
-
匿名内部类,没有类名,直接new I接口(),不用像普通别的类一样需要implements接口,然后在new 类的对象,去点方法.
-
lambda表达式:前提是接口为函数式接口(只有一个方法),多个参数
可以都去掉参数类型,不去掉要加上括号
定义一个函数式接口 interface Ilike{ void lambda(int a); } Ilike love = new Ilike() { @Override 匿名内部类 public void lambda(int a) { System.out.println("输出"+a); } }; love.lambda(520); lambda方式 Ilike love = a-> System.out.println("我"+a); love.lambda(520);
-
模拟线程stop
private boolean flag = true; @Override public void run() { int i = 0; while (flag){ System.out.println("线程执行到->"+i++); } } public void stop(){ this.flag = false; } public static void main(String[] args) { xiancheng xian = new xiancheng(); new Thread(xian).start(); for (int i = 0; i < 500; i++) { System.out.println("mian->"+i); if (i==300){ xian.stop(); System.out.println("该线程停止了"); } } }
-
模拟sleep倒计时,和获取当前时间,(每个对象都有一个锁,sleep不会释放锁)
public static void main(String[] args) { try { daoJiShi(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void daoJiShi() throws InterruptedException { int num = 10; while (true){ Thread.sleep(1000);//1秒的延迟 System.out.println(num--); if (num<0){ break; } } } public class TestSleep { public static void main(String[] args) { 获取系统当前时间 Date startTime = new Date(System.currentTimeMillis()); while (true){ try { Thread.sleep(1000); 修改时间格式 System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime)); 更新当前时间 startTime = new Date(System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } }
-
Join插队
class JoinTest implements Runnable{ @Override public void run() { for (int i = 0; i <100; i++) { System.out.println("vip线程->"+i); } } public static void main(String[] args) throws InterruptedException { JoinTest join = new JoinTest(); Thread thread = new Thread(join); thread.start(); for (int i = 0; i <100 ; i++) { if (i==50){ thread.join();//插队 } System.out.println("main"+i); } } }
-
Priority线程优先级:
- 主线程不能更改,默认5,可设置优先级为1-10
Thread.currentThread().getPriority()
主线程默认优先级- 先设置优先级,在启动
- 优先级低意味着获得调度的概率低,依然会被调用
-
守护线程
-
线程分为用户线程和守护线程
-
虚拟机必须确保用户线程执行完毕(就是main())
-
虚拟机不用等到守护线程执行完毕
-
守护线程如后台记录操作日志,监控内存,垃圾回收
-
默认是false用户进程正常线程都是用户线程,true就是守护进程
-
thread.setDaemon(true)
-
-
synchronized同步
- synchronized修饰符:锁的是this,这个类本身
- synchronized(Obj){}同步块:
synchronized(变量或this){逻辑代码}
- Obj称之为同步监视器
- Obj可以是任何对象,但是推荐使用变化的量,如增删改的对象
- 修饰符同步方法中,无需指定同步监视器,因为同步方法的同步监视器就是this就是这个对象本身,或者是class
//synchronized 线程安全 线程排队购买 public class Test { public static void main(String[] args) { BuyPiao mp = new BuyPiao(); new Thread(mp,"小明").start(); new Thread(mp,"小红").start(); new Thread(mp,"小绿").start(); } } class BuyPiao implements Runnable{ //票 private int piao = 10; private boolean flag = true;//外部停止方式 @Override public void run() { //买票 while (true){ try { buy(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void buy() throws InterruptedException { //判断是否有票 if (piao<=0){ flag = false; return; } //模拟延时 Thread.sleep(100); //买到票 System.out.println(Thread.currentThread().getName()+"买到"+piao--); } }
-
CopyOnWriteArrayList
安全类型集合 -
死锁:多个线程互相持有对方需要的资源,然后形成僵持
只要两个线程不同时抱一个线程锁就可以了.
- Lock是显示锁,只能锁代码块,
JVM
将花费更少的时间来调度线程,性能更好,扩展性好(有很多子类)
public void run() {
while (true){
try{
lock.lock();
if (num>=0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(num--);
}else {
break;
}
}finally {
lock.unlock();
}
}
-
生产者和消费者模式 后厨(生产者)–>吧台(缓冲区)–>顾客(消费者)
-
wait():表示线程一直等待,知道其他线程通知,与sleep不同,会释放锁
-
wait(long timeout):指定等待的毫秒数
-
notify():唤醒一个处于等待状态的线程
-
notifyAll():唤醒同一个对象上所有调用wait()方法的线程,优先级别高的线程优先调度
-
都是Object类的方法,都只能在同步或同步代码块中用,否则有异常
-