同步方法和同步块
同步方法定义: 在函数返回类型前synchronized
同步方法保证同一时间点执行该方法线程只有一个。注意:不同类对象中的方法锁是不一样的。
同步块定义:synchronized(要锁的对象){}
同步块保证同一时间点执行被锁代码块的线程只有一个。
CopyOnWriteArrayList
安全列表,普通列表ArrayList多个线程同时执行时可能会出现一个数组下标对应的地址被写入多次的情况
静态代理
两个实现了相同的接口类即可实现静态代理, runable接口的执行使用了静态代理技术
MyThread a=new Mythread();
Thread(a).start();//这里线程开启之后,执行Thread类中的run方法,而Thread类的run方法又调用了MyThread类中的run方法
线程协作方法
wait() 让线程进入等待状态,
notify() 随机唤醒一个等待状态的线程,
notifyAll() 唤醒所有等待状态的线程。
注意,这三个方法必须在同步方法或同步块的包裹下执行,不能用lock
这三个方法是object类中的函数
线程池
频繁创建和销毁线程,对性能影响很大,故引入线程池,即事先创建多个线程,放入线程池中,当需要用到线程时,从线程池中取出线程,线程执行完后,再放回线程池中
三种多线程的实现步骤
1、继承Thread类的方法(由于java不支持多继承,所以使用该方法线程不灵活,具体表现在同一个类对象只能应用于一个线程)
步骤:1.继承Thread类 2.重写run方法 3.线程启动:继承了Thread的类.start()
2、实现runnable接口的方法(使用了静态代理技术,线程无返回结果)
步骤:1.实现runnable接口 2.重写run方法 3.线程启动:Thread(实现runnable接口的类的对象).start()
3、实现callable接口的方法(使用了线程池技术,线程有返回结果)
步骤:1.实现callable接口 2.重写call方法 3.线程启动:分为四步,如下
(1)创建服务,ExecutorServer ser=Executor.newFixedThreadPool(线程池大小)
(2)提交执行,Future r1=ser.submit(实现callable接口的类的对象);
(3)获取返回结果,String rs1=r1.get();
(4)关闭服务,ser.shutdown();
ps:runnable接口也可以使用线程池技术,线程启动分为3步,如下
(1)创建服务
(2)提交执行,ser.Execute(实现runnable接口的类的对象);
(3)关闭服务,ser.shutdown();
lambda表达式
简化了定义一个类的程序语句:由匿名内部类演变而来。
能用lambda表达式的前提条件:1.该类借助接口实现 2.接口是函数式接口(即接口内只有一个方法,可以有属性)
匿名内部类:(必须借助接口或父类)
Like like=new Like{//这里Like是一个事先定义好的接口,且Like中只有一个方法like()
@Override
public void like() {
System.out.println("匿名内部类");
}
}
lambda表达式:(以下代码等价于上面代码)
Like like=()->{
System.out.println("lambda表达式");
}
带参数的lambda表达式:
Like like=(a,b)->{
System.out.println("lambda表达式");
}
这里顺便巩固以下重写和重载函数,重写函数必须保证方法名,返回值,形参个数,类型,顺序都与原函数一样,而重载只需方法名一致,所以这里lambda表达式中(int a,int b)可以简化为(a,b) 。
Thread类中的常用方法
线程的四个状态:创建状态,阻塞状态(sleep和wait后线程都是进入阻塞态),就绪状态,运行状态,死亡状态。
1.停止线程:不推荐使用jdk自带的stop和destroy强制停止线程,可以设置一个标志位flag来停止线程。
2.线程休眠:Thread.sleep(毫秒数);
3.线程礼让:Thread.yield();让线程从运行状态变为就绪状态,cpu重新进行调度。
4.线程强制执行:Thread.join();阻塞所有其他线程,等待其执行完毕其余线程才可执行。
5.设置线程优先级:Thread.setPriority(整数) 范围[1,10] 在线程启动前设置才有效。主线程无法设置优先级,默认优先级为5
注意:优先级高的线程不能保证一定先于优先级低的进程运行。
6.守护进程:Thread.setDaemon(true) 在进程创建后将进程设置为守护进程
Jvm必须确保用户进程执行完毕,无需等待守护进程执行完毕。
守护进程主要作用是记录操作日志,垃圾回收,内存监控
7.线程状态查询:Thread.State=Thread.getState();
以上方法是Thread类中成员函数,成员变量。在进程内部(即run方法中)对进程进行操作使用 Thread.函数(),在进程外部对进程进行操作使用 Thread类对象.函数() 。