java多线程
文章目录
前言
java多线程技术相关用法呈现
一、生成多线程
1.继承Thread类
创建一个Thread的子类的一个实例即创建了一个线程
换句话说,它的一个实例 就是一个线程
利用此方法,创建一个Thread的子类的一个实例就是创建了一个线程,子类中描述了一个线程要做的工作,因此若多线程要完成不同的工作就要创建多个不同的子类。
一个子类多次实例化就创建了多个相同的线程,需要注意的是:若子类中含有static类变量,那么这一个子类的多个线程便会操作同一个变量。
2.实现Runnable接口
将Runnable的一个实现类的一个实例放入Thread( ) 构造器中,通过Thread构造器创建线程
通过这种方法,放入同一个实现类实例创建出的多个线程总是会操作这一个实例内的同一些成员变量,当然也完成相同的操作
因此要完成不同的操作就需要不同的实现类
3.实现Callable接口
将Callable的实现类的一个实例放入FutureTask构造器中创建FutureTask实例,再将Futuretask实例放入Thread构造器中创建出一个线程
4.线程池
调用Executors的newFixedThreadPool( )或.newCachedThreadPool(
)方法创建出ExecutorService的一个实例,调用该实例的execute( )方法或submit(
)方法,在方法中提交含有线程操作的实现Runnable接口或Callable接口实现类对象
说明:
execute( )适用于Runnable
submit( ) 适合适用于Callable
//1.提供指定线程数量的线程池
ExecutorService service = Executors.newFixedThreadPool(10);
ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
//设置线程池的属性
// System.out.println(service.getClass());
// service1.setCorePoolSize(15);
// service1.setKeepAliveTime();
//2.执行指定的线程的操作。需要提供实现Runnable接口或Callable接口实现类的对象。
service.execute(new NumberThread()); //适合用于Runnable
// service.submit(); 适合适用于Callable
//关闭线程池
service.shutdown();
二、锁
一个Thread子类的实例只能构造一个线程
一个Runnable实现类的实例可以构造多个线程
synchronized(同步监视器){需要被同步的代码}
1.Syncronized同步锁
关于锁的选择:
-
自行创建,共用对象,如下面demo中的Object对象。
-
使用this表示当前类的对象
-
继承Thread的方法中的锁不能使用this代替,因为继承thread实现多线程时,会创建多个子类对象来代表多个线程,这个时候this指的时当前这个类的多个对象,不唯一,无法当作锁。
-
实现Runnable接口的方式中,this可以当作锁,因为这种方式只需要创建一个实现类的对象,将实现类的对象传递给多个Thread类对象来当作多个线程,this就是这个一个实现类的对象,是唯一的,被所有线程所共用的对象。
-
使用类当作锁,以下面demo为例,其中的锁可以写为WindowThread.class, 从这里可以得出结论,类也是一个对象
同步代码块
private int tiketsNum = 100;
//由于,Runnable实现多线程,所有线程共用一个实现类的对象,所以三个线程都共用实现类中的这个Object类的对象。
Object obj = new Object();
//如果时继承Thread类实现多线程,那么需要使用到static Object obj = new Object();
public void run() {
//Object obj = new Object();
//如果Object对象在run()方法中创建,那么每个线程运行都会生成自己的Object类的对象,并不是三个线程的共享对象,所以并没有给加上锁。
while (true) {
synchronized (obj) {
if (tiketsNum > 0) {
try {
//手动让线程进入阻塞,增大安全性发生的概率
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":\t票号:" + tiketsNum + "\t剩余票数:" + --tiketsNum);
} else {
break;
}
}
}
同步方法
同步方法仍然涉及到同步监视器,只是不需要我们显示的声明。
非静态的同步方法,同步监视器是:this。
静态的同步方法,同步监视器是:当前类本身。
class Window02Thread implements Runnable {
private int tiketsNum = 100;