JAVASE——多线程

 

目录

创建线程

继承Thread类

实现Runnable接口 

实现Callable接口、FutureTask类实现

线程的常用方法

 线程安全

线程同步

同步代码块

同步方法

lock锁

线程池

创建线程池

 处理Runnable任务

处理Callable任务


线程是一个程序内部的一条执行流程

创建线程

继承Thread类

  • 1、定义一个子类继承Thread类,成为一个线程类
  • 2、重写Thread类的run方法
  • 3、在run方法中编写线程的任务代码
  • 4、创建线程类的对象,代表县城
  • 5、调用start方法,启动线程

优点:编码简单

缺点:线程类已经继承Thread,无法继承其他类,不利于功能的扩展

注意:

  • 启动线程必须是调用start方法,而不是run方法,直接调用run方法会被当成普通方法执行,此时相当于还是单线程执行
  • 只有调用start方法才是启动一个新的线程执行

实现Runnable接口 

  •  1、定义一个线程任务类实现Runnable接口。
  • 2、重写run方法,设置线程任务
  • 3、创建MyRunnable任务对象
  • 4、把MyRunnable任务对象交给Thread处理
  • 5、调用线程对象的start()方法启动线程

优点:任务类只是实现接口,可以继续继承其他类、实现其他接口、扩展性强。

缺点:需要多一个Runnable对象

匿名内部类写法

  • 1、可以创建Runnable的匿名内部类对象
  • 2、再交给Thread线程对象
  • 3、再调用线程对象的start()启动线程 

实现Callable接口、FutureTask类实现

1、创建任务对象

  • 定义一个类实现Callable接口,重写call方法,封装要做的事情,和要返回的数据
  • 把Callable类型的对象封装成FutureTask(线程任务对象)

2、把线程任务对象交给Thread对象

3、调用Thread对象的start方法启动线程

4、线程执行完毕后、通过FutureTask对象的get方法去获取线程任务执行的结果

 优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;可以在线程执行完毕后去获取线程执行的结果

缺点:编码复杂一点

线程的常用方法

Thread的常用方法

public void run()

线程的任务方法
public void start()启动线程
public String getName()获取当前线程的名称,线程名称默认是Thread-索引
public void setName(String name)为线程设置名称
public static Thread currentThread()获取当前执行的线程对象
public static void sleep(long time)让当前执行的线程休眠多少毫秒后,再继续执行
public final void join()...让调用当前这个方法的线程先执行完
public Thread(String name)可以为当前线程指定名称
public Thread(Runnable target)封装Runnable对象成为线程对象
public Thread(Runnable target,String name)封装Runnable对象成为线程对象,并指定线程名称

 线程安全

多个线程,同时执行访问一个共享资源,存在修改该共享资源

线程同步

让多个线程先后依次访问共享资源,这样就可以避免出现线程安全问题

方案

加锁:每次只允许一个线程加锁,加锁后才能进入访问,访问完毕后自动解锁,然后其他线程才能进来

同步代码块

作用:把访问共享资源的核心代码给上锁。

synchronized(同步锁){

        访问共享资源的核心代码

}

原理:每次只允许一个线程加锁后进入,执行完毕后自动解锁,

  • 对于实例方案一般同步锁用this作为锁对象
  • 对于静态方案建议使用字节码(类名.class)对象作为锁对象

同步方法

作用:把访问共享资源的核心方法给上锁。

修饰符 synchronized 返回值类型 方法名称(形成列表){

        存在共享资源的代码

}

 锁对象与同步代码块一样

lock锁

创建出锁对象进行加锁和解锁

ReentrantLock()获得lock对象

private final Lock lk = new ReentrantLock();

lk.lock();上锁

try{

}finally{

方finally里进行解锁

lk.unlock();

}

线程池

可以复用线程的技术

创建线程池

方式一:使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象。

方式二:使用Executor(线程池的工具类)调用方法返回不同特点的线程池对象。

  •  参数一:corePoolSize:指定线程池的核心线程的数量。
  • 参数二:maximumPoolSize:指定线程池的最大线程数量
  • 参数三:keepAliveTime:指定临时线程的存活时间
  • 参数四:unit:指定临时线程存活的时间单位
  • 参数五:workQueue:指定线程池的任务队列
  • 参数六:threadFactory:指定线程池的线程工厂
  • 参数七:handler:指定线程池的任务拒绝策略

 处理Runnable任务

void execute(Runnable command)

什么时候才会创建临时线程? 

新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。

什么时候会拒绝新任务?

核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝任务

处理Callable任务

Future<T> submit(Callable<T> task)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值