多线程
这个是JAVA SE的重要知识之一,所以再次重新复习一遍,记录下重点
多任务: 看起来是多个任务都在做其实是我们大脑在同一时间做一件事情
多线程:例子,道路堵塞,游戏
调用run和strat方法的区别
主线程调用run()方法是线程执行到run()方法结束然后才接着往下继续执行
而调用start()方法则是开辟了两条执行路劲,strat走它的主线程走它自己的,并行交替执行
//进程是程序执行的过程,包含至少一个的线程
//一个cpu只是模拟着多线程,同一个时间cpu只能执行一个代码,因为切换的很块,电脑时间单位是纳秒,真正的多线程是多个cpu即多核
main()叫做主线程,jvm给的gc线程清理垃圾,守护线程,没有创建也会有
三种方式创建接口
- 继承Thread类 // 实现:new Therad().start();,单继承局限性无法多线程
- 实现Runnable接口(重点) //可以多线程灵活方便
- 实现Callable接口(了解) //重写call方法,开启关闭服务,
好处: 1. 有返回值Callable return true; 2. 可以抛出异常
网图下载
commons-io下载图片的jar包
FileUtils.copyURLToFile(new URL(url),new File(name)); //工具类
public void run(){ //线程的执行体
WebDownloader web=new WebDownloader();
web.downloader(url,name);
System.out.print("下载了文件",name);
}
//主类:
Thread类名 t1=new Thread类名(url:"图片网络地址",name:"要命名的名字加格式");
t1.start();
实现Runable
new Thread(实现类实例对象).start();
模拟龟兔赛跑
public class Threadtest implements Runnable {
private static String winnner;
@Override
public void run() {
// TODO 自动生成的方法存根
while(true) {
for(int i=0;i<100;i++) {
//模拟兔子睡觉
if(Thread.currentThread().getName().equals("兔子")&&i%10==0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
boolean flag=winner(i);
if(flag) {
break;
}
System.out.print(Thread.currentThread().getName()+"走了"+i+"步");
}
}
}
private boolean winner(int steps) {
if(winnner!=null) {
return true;
}
if(steps>=100) {
winnner=Thread.currentThread().getName();
System.out.println("winner is"+winnner);
return true;
}
return false;
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
Threadtest t1=new Threadtest();
new Thread(t1,"兔子").start();
new Thread(t1,"乌龟").start();
}
静态代理
例子:你+婚庆公司+结婚(实现结婚接口)
//婚庆公司作为静态代理,他代理真实对象,真实对象和代理对象都要实现结婚接口,然后剩下的事情就算把你当作真实对象传进婚庆公司,然后执行方法由实例婚庆公司调用
好处:
/*代理对象帮助对象做很多真实对象做不了的事情
真实对象专注做自己的事
new WeddingCompany(new You()).HappMarry();
new Thread( ()-> System.out.println("我爱你")).start();
同理可得,所以多线程代理了Runable接口实现了start()方法
*/
lamda表达式
//实质属于函数式编程的概念,避免内部类过多
new Thread( ()-> System.out.println("我爱你")).start();
如果只包含一个抽象发=方法就算函数式接口
public interface Runnable{
public abstract void run();
}
线程的停止
Thread.stop();
线程的休眠
线程休眠方法Thread.sleep(时间);
Join
合并线程,插队 thread.join(); //执行完才执行其他的
线程的观测状态
新生,就绪,运行->阻塞,死亡
Thread.state (NEW,RUNABLE,WAITING,dead)
线程的优先级
1-10 优先级高的先跑,获取CPU的调度概率高
Thread.MIN_PRIORITY=1
Thread.MAX_PRIORITY=10
Thread.NORM_PRIORITY=5
getPriority() setPriority(num);
///设定优先级建议在start前面
###
守护线程
//线程分为用户线程和守护线程
//确保用户线程执行完毕
//虚拟机不用等待守护线程
==作用:==后台记录操作,监控内存,垃圾回收等
//设置守护线程
thread.setDaemon(true);
线程同步机制 抢票-队列+锁
并发:同一个对象被多个线程使用
对象进入对象的等待池排队
食堂打饭——食堂大妈等于synchronized锁 ---安全性
若将synchronized加在方法上会影响效率,需要修改的内容才需要锁
//同步块
synchronized(obj){
//可以实现同一个共享资源的同步但实现不了不同线程之间的通信
//生产消费者模式
}
//线程通信方法 wait() 等待唤醒 notify()唤醒
LoCK锁
三大不安全案例
不安全的抢票,不安全的取钱,不安全的集合会覆盖