多线程创建方式:
1. 继承Thread类(不带有返回值):
1.创建一个继承于Thread类的子类
2.重写Thread类的run()方法
3.创建Thread类的子类的对象
4.通过创建的对象调用start()
2. 实现Runnable接口(不带有返回值):
1.创建一个实现Runnable接口的类
2.实现类去实现Runnable中的抽象方法 run()
3.创建实现类的对象
4.通过Thread类的对象调用start()
与继承Thread类比,开发中常用实现Runnable接口的方法来创建,因为:
1.实现的方式为接口,不影响调用的类继承其他类
2.适合多个线程处理的数据有共享数据的情况
3.实现Callable接口(带有返回值):
1.创建一个Callable接口的实现类
2.在继承类中实现call方法
3.创建Callable接口实现类的对象
4.将创建的Callable接口实现类的对象传递到FutureTask构造器中,创建FutureTask的对象
5.将创建的FutureTask的对象做为参数传递到Thread类的构造器中,创建Thread类的对象并调用start()
6.若需要返回值,则通过FutureTask的对象get()方法获取返回值。
4.使用线程池:
1.创建指定数量的线程池 ExecutorService service = Executors.newFixedThreadPool(10);
2.执行线程操作 serivce.excute(适用于Runnable); service.submit(适用于Callable);
3.关闭连接池 service.shutdown();
线程池的配置:
将ExecutorService service转为ThreadPoolExecutor类再进行属性配置
好处:提高响应速度(减少了创建新线程的时间,降低资源消耗、可重复利用线程池中的线程,不需要每次都创建,便于线程管理)
线程优先级(引用于菜鸟教程)
线程的优先级
每一个 Java 线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。
Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。
默认情况下,每一个线程都会分配一个优先级 NORM_PRIORITY(5)。
具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器资源。但是,线程优先级不能保证线程执行的顺序,而且非常依赖于平台。
线程安全的解决:
1.同步代码块(synchronized):
synchronized(同步监视器){
//要执行的有共享数据的代码块
}
同步监视器可以为任意Object对象,视情况而定。但运行该代码块多个该线程的同步监视器应该为同一监视器
2.同步方法(synchronized):
在方法体中声明synchronized
同步方法的同步监视器对象为该方法所在类
3.Lock锁(ReentrantLock):
1.实例化ReentrantLock
2.将操作共享数据的代码放进try{}finally{}中,并在try前调用lock()方法
3.在finally中调用unlock()方法
Lock与synchronized的异同:
同:都可以解决线程安全的问题
异:synchronized在执行完后自动释放同步监视器,而lock需要手动去启动(lock())和关闭(unlock())
4.三种方式的有限使用顺序:
Lock-->同步代码块-->同步方法
线程通信
1.涉及到的三个方法:
1.wait():执行后当前线程进入阻塞状态
2.notify():执行后唤醒wait()中的线程,如果有多个线程wait(),就唤醒级别高的,适用于两个线程
3.notifyAll():执行后唤醒所有线程
2.三个方法的说明:
1.三个方法必须在同步代码块或同步方法中使用
2.不同于sleep()方法定义在Thread类中,三个方法定义在Object类中,所以三个方法必须由该代码块的同步监视器调用