线程
Thread类
成员方法
public String getName() :获取当前线程名称。main主方法不能直接用这个方法,
用currentThread().getName()获取
public static Thread currentThread() :获取当前线程名称。
public static void sleep(long millis);使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),毫秒结束后,线程继续执行
构造方法
public Thread(String name) :给线程改名字
也可以直接对象名点setname();
创建线程的第二种方式
实现Runnable接口
1.创建一个Runnable接口的实现类
2.在实现类中重写Runnable接口的run方法,设置线程任务
3.创建一个Runnable接口的实现类对象
4.创建Thread类对象,构造方法中(括号中)传递Runnable接口的实现类对象
5.调用Thread类中的start方法,开启新的线程,执行run方法
Thread和Runnable的区别
Runnable的优势:
1.避免了单继承性
2.增强了程序的扩展性,降低了程序的耦合性(解耦)
实现Runnable接口的方式,把设置线程的任务和开启新线程进行了分离(解耦)
实现类中,重写了run方法:用来设置线程任务
创建Thread类对象,调用start方法:用来开启新线程
匿名内部类方式实现线程的创建
Thread方式:
new Thread(){
@Override
public void run(){
重写run方法的内容
}
}.start();
线程接口Runnable:
new Thread(new Runnable)(){
@Override
public void run(){
重写run方法的内容
}
}).start();
多线程访问共享数据,会引发安全问题
解决:让一个线程在访问共享数据时,无论是否失去了CPU的执行权,
让其他的线程只能等待,等待当前线程完成再进行
解决:
第一种方式
同步代码块
格式:
synchronized(锁对象){
可能会出现线程安全问题的代码(访问了共享数据的代码)
}
注意:
要先创建一个锁对象,可以使任意类型
锁代码中的对象可以是任意的对象
要保证多个线程的锁对象是同一个
锁对象作用:吧同步代码块锁住,只让一个线程在同步代码块中执行
同步锁保证了只能有一个线程在执行共享数据,保证了安全,降低了效率
第二种方式
定义一个同步方法
格式:
public synchronized void method(){
可能会产生线程安全问题的代码
}
1.把访问了共享数据的代码抽取出来,放到一个方法中
2.在方法上添加synchronized修饰符
静态同步方法
第三种方式
Lock锁
成员方法
void Lock();获取锁
void unLock();释放锁
1.在成员位置创建一个ReentrantLock对象
2.在可能会出现安全问题的代码前调用Lock接口方法lock()方法获取锁
3.在可能会出现安全问题的代码后调用Lock接口中的unlock()方法释放锁
Object类中的方法
void wait();让线程进入无限等待,只有唤醒才能继续执行
void notify();唤醒在此监视器上的单个线程
void notify();唤醒在此监视器上的所有线程
等待与唤醒
wait等待
notify唤醒线程
notifyALL唤醒所有线程
线程池
Excutors类 用来生产线程池
public static ExecutorService newFixedThreadPool(int nThreads) :返回线程池对象。固定线程数
静态方法
参数:int nTreads;创建线程池中包含的线程数量
返回值:ExecutorService接口,返回的是ExecutorService接口的实现类对象,可以使用ExcutorService接口来接收(面向接口编程)
1.使用线程池工厂类Executors里面提供的静态方法newFixedThreasPool生产一个指定数量的线程池
2.创建一个类,实现Runnable接口,重写run方法,设置线程任务
3.调用ExecutorService中的方法submit,传递线程任务(实现类),开启线程,执行run方法
4.调用ExecutorService中的方法shutdown销毁线程池(不建议使用)
ExecutorService es = Executors.newFixedThreadPool(设置线程数);
es.submit(new RunnableImpl ); 参数串传的是自己定义的线程任务;submit方法传递线程任务,开启线程,执行run方法
es.shutdown();销毁线程池,不建议
Lambda表达式
1.Lambda表达式必须具有接口,且要求接口中有且仅有一个方法
2.Lambda必须具有上下文推断
重视结果,不重视过程
Lambda表达式的标准格式:
(参数列表) -> {一些重写方法的代码};
有三部分组成,一些参数,一个箭头,一段代码
():接口中的抽象方法的参数列表,没有参数,就空着,多个参数都好分隔
->:传递的意思,把参数传递给方法体{}
{}:重写接口的抽象方法的方法体
Lambda的无参无返回值使用:
1.创建接口,接口中有一个抽象方法
2.测试类中定义方法,传递接口类型为参数,调用接口抽象方法
3.main主方法调用测试类定义的方法(用Lambda表达式):
测试类中定义的方法(()->{要执行的语句});
使用数组存储多个Person对象
对数组中的对象进行Arrays.sort方法进行年龄升序排序
Lambda有参有返回值使用:
1.先用数组存储对象
2.(用Lambda表达式);
用Arrays.sort((参数就是数组对象,(参数就是o1,o2))->{方法体就是returno1-o2}),
再遍历数组
Lambda表达式的有参又返回使用:
1.定义一个接口,定义一个抽象方法(有参数)
2.在测试类中定义一个方法,以(接口和抽象方法的参数)为参数
重写接口中的方法
3.在main主方法中,调用测试类的方法(使用Lambda表达式)
Lambda表达式的省略格式:可推倒,可省略
1.(参数列表):括号中参数列表的数据类型一致,可以省略不写
2.(参数列表):括号中的参数如果只有一个,那么类型和()都可以省略
3.(一些代码):如果{}中的代码只有一行,无论是否有返回值,都也已省略({},return,分号);
注意:要省略{},return,分号,必须三个一起省略
|
|