1.process进程(程序) thread线程
main线程
2.多线程是是模拟处理的,真正的多线程是物理上的几个线程
1.线程不能人为干预
2.每个线程内存交互,控制不当数据不一致
3.实现
extend Thread(oop单继承局限性) 重写run方法(与main线程交替执行)
1. 如果不是多线程 按代码执行顺序执行
2. 线程开启不一定立即执行,由cpu调度
3. 网上图片变文件 多线程下载Runnable(推荐)(可以多个线程操作同一个对象,会有线程重复消费问题)
1.new Thread(xxximplRunable).start();;
Callable 工作3 5年后的重点
- 实现Callable 定义返回类型
- 重写call方法 public Boolean call(){ return true;}
- 创建执行访问
ser=Executors.newFixedThreadPool(3);- 提交执行任务
Future r1=ser.submit(t1);
Future r2=ser.submit(t2);- 获得执行结果
boolean res1=r1.get();
boolean res2=r2.get();- 关闭服务
ser.shutdownNow();
4.龟兔赛跑
if(){
}//有return,else可以省略
5.静态代理模式(设计模式的装饰模式) 好处 代替真实对象做,还可以做一些真实对象不能做的
class staticProxy{
public static void main(String[] args) {
WeddingCompany weddingCompany = new WeddingCompany(new You());
weddingCompany.happyMarry();
//和线程一样的道理
new Thread(()->{
System.out.println("结婚拉");
}).start();
}
}
public interface Marry {
void happyMarry();
}
class You implements Marry{
@Override
public void happyMarry() {
System.out.println("小狂神要要结婚了");
}
}
class WeddingCompany implements Marry{
private Marry target;
public WeddingCompany(Marry target){ //构造方法没有返回值
this.target=target;
}
private void before() {
System.out.println("结婚前整理现场");
}
private void after() {
System.out.println("结婚后收取费用");
}
@Override
public void happyMarry() {
before();
this.target.happyMarry();
after();
}
}
6.lambda表达式(匿名内部类)(一个方法的接口就是函数式接口)
进化过程
- 一个类一个接口 ,类实现接口
- 静态内部类,在类里面写静态方法 实现接口
- 局部内部类 直接在方法里面写类 都可以new出来
- 匿名内部类
new xx(){xxx};//接口可以new出来- lambda (方法的参数 int a)->{xxx}; (方法的参数 a)->{xxx}; //去参数类型,多个参数要去都去
a->{} //去括号,只有一个参数时
a->xxx //去花括号,只有一行时
7.线程的状态 5个状态 sleep() wait()可以进入阻塞状态
//线程怎么停止,不建议使用 jdk自己的stop()方法
//写个while(flag)死循环+标志物模拟即可
public class ThreadStop {
public static void main(String[] args) {
MyThread myThread = new MyThread();
new Thread(myThread).start();
for (int i = 0; i < 100000; i++) {
if (i==99999){
myThread.stop();
}
}
}
}
class MyThread implements Runnable{
boolean flag=true;
int i=0;
@Override
public void run() {
while(flag){
System.out.println("程序运行中"+i);
i++;
}
}
public void stop(){
flag=false;
}
}
8.线程睡眠 sleep 可以放大问题的发生性,每个对象都有一个锁,sleep不会释放锁
9.yield礼让, a使用cpu中然后礼让b,和b在就绪状态继续竞争(不一定成功 看cpu心情)
//如果又得到cpu了,那继续执行下面的代码
public class ThreadYield {
public static void main(String[] args) {
new Thread(new MyThread3(),"a").start();
new Thread(new MyThread3(),"b").start();
}
}
class MyThread3 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程让步前");
Thread.yield();
System.out.println(Thread.currentThread().getName()+"线程让步后");
}
}
10.join强制插队(非常霸道,必须要强制执行完他)不推荐使用,会让其他线程阻塞
//注意是new出来后才有的方法join()代表现在这个对象,要强行插队
public class ThreadJoin {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new MyThread4());
thread.start();
for (int i = 0; i < 100; i++) {
if (i==20){
thread.join();
}
System.out.println(Thread.currentThread().getName()+i);
}
}
}
class MyThread4 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
}
}
11.观察Thread的状态 5.for 死亡后不能再启动
Thread.State state=thread.getState();
12.优先级(设置,不一定一定优先,只是概率高,就算放在后面概率也高) 范围[1,10] main默认是5公平
//得到优先级
Thread.currentThread().getPriority();
//注意先设置优先级后启动
t1.setPriotity(1);
t1.start();
13.守护线程 daemon线程
- 用户线程main线程,任务结束就停止
- 守护线程 gc 日志记录线程 监控内存… 永不停止
thread.setDaemon(true);//设置是守护线程,用户结束了,jvm不用管守护线程,程序结束了jvm就结束了,上帝就结束了 god blessed with me 就是守护线程一直守护用户线程,用户线程消失,上帝守护线程也消失
人生不过3万天…
- 并发: 多个线程访问同一个对象(一拥而上)
- 线程并发加锁的问题:
1. 一个拥有锁会导致其他需要这个锁的线程挂起
2. 加锁释放锁需要很多的上下文切换和调度延时,有性能问题
3. 优先级高的锁等低优先级的锁,会导致性能低下,有性能问题- 三大不安全案例 取票 银行同时多个线程取钱 ArrayList线程不安全
4.for
new Thread(()->{list.add(Thread.currentThread().getName())});
sout(list.size);//数量丢失,当超多线程同时访问的时候,创建多个线程操作同一list
15.同步方法
- private保证对象只能被方法访问(get set方法)
- 声明synchronized在方法上会影响效率,默认锁的是整个this对象,应该锁我们需要的,不然失效(锁this)
- 使用同步块,以上面list为例,锁的是需要 增删改的对象
synchronized(list){
}
15.JUC是并发包,写好了线程安全的东西 CopyOnWriteArrayList是线程安全的list
可以直接使用
transient有序的 volatile唯一的 java关键字