文章目录
一、多线程的实现
方案一:继承Thread类
步骤:
- 子定义一个子类myThread继承Thread,重写其run方法
- 创建myThread对象
- 调用对象的start()方法启动线程
代码实现:
public class test {
public static void main(String[] args) {
//2、
Thread t = new myThread();
t.start();
System.out.println("主线程执行");
}
}
//1、定义mythread继承Thread,重写其run方法
class myThread extends Thread{
@Override
public void run() {
System.out.println("子线程执行");
}
}
优点:编码简单
缺点:无法继承其他类,不利于扩展
方案二:实现Runnable接口的类
步骤:
- 定义myRunnable类实现Runnable接口,重写其run方法
- 创建对象交给Thread处理
- 调用线程对象的start方法
代码实现
public class test {
public static void main(String[] args) {
//2、创建任务对象
Runnable r = new myRunnable();
//3、把任务对象交给thread处理
Thread t = new Thread(r);
t.start();
for (int i=0;i<5;i++) {
System.out.println("主线程执行"+i);
}
}
}
//1、创建一个任务类实现Runnable接口
class myRunnable implements Runnable{
@Override
public void run() {
for (int i=0;i<5;i++) {
System.out.println("子线程执行"+i);
}
}
}
//使用匿名内部类简化代码
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("子线程执行"+i);
}
}
});
方案三:实现Callable接口(建议)
步骤:
- 定义类实现Callable接口,重写call方法
- 用FutureTask把Callable对象封装成线程对象
- 把封装好的线程对象交给Thread处理,调用Start方法
- 线程结束后,通过FutureTask的get方法获取执行结果
public class test {
public static void main(String[] args) {
//2、创建Callable对象
Callable c = new myCallable();
//3、用FutureTask来封装Callable对象
FutureTask<String> f = new FutureTask<>(c);
//4、用Thread来接收FutureTask对象
Thread t = new Thread(f);
t.start();
try {
//通过FutureTask对象调用get方法获取线程执行call方法返回的结果
System.out.println(f.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
//1、创建myCallable实现Callable接口,重写其call方法
class myCallable implements Callable<String>{
@Override
public String call() throws Exception {
return "子线程";
}
}
二、线程同步
方式一:同步代码块
代码如下(示例):
synchronized (锁对象) {
共享资源代码块
}
对于实例方法,建议采用this指针作为锁对象
对于静态方法,建议采用类名.class作为锁对象
方式二:同步方法
代码如下(示例):
private static synchronized void test(){
只需在返回值前加上synchronized 这个方法就成为同步方法了
}
方式三:Lock锁
private final Lock lock = new ReentrantLock();//创建锁
lock.lock();//上锁
lock.unlock();//解锁
因为Lock是接口不能直接实例化,所以这里用了它的实现类ReentrantLock来构造对象
加final保证了对象只能赋值一次,唯一不可替换
三、线程通信
等待和唤醒方法
void wait();
void notify();
void notifyAll();
由锁对象来调用方法
四、线程池
线程池实现的API
ExecutorService接口代表了线程池
ThreadPoolExecutor是此接口的实现类
ThreadPoolExecutor(int corePoolSize, //核心线程数
int maximumPoolSize,//最大线程数
long keepAliveTime,//临时线程存活时间
TimeUnit unit,//时间单位
BlockingQueue<Runnable> workQueue,//任务队列,任务对象是Runnable或者Callable类型的
ThreadFactory threadFactory,//线程工厂
RejectedExecutionHandler handler)//任务队列满了之后对任务的处理方法
线程池执行Runnable类型的任务
//1、初始化线程池
public class test {
public static void main(String[] args) throws Exception{
//1、初始化线程池
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 5, 3,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(5),
Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
//2、创建任务对象
Runnable r = new myRunnable();
//3、把任务放进池子中
pool.execute(r);
}
class myRunnable implements Runnable{
@Override
public void run() {
System.out.println("hh");
}
}
线程池执行Callable类型的任务
public class test {
public static void main(String[] args) throws Exception{
//1、初始化线程池
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 5, 3,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(5),
Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
//2、创建Callable任务对象
Callable<String> c = new myCallable();
//3、submit提交任务,用Future接收返回值
Future<String> t = pool.submit(c);
//4、输出线程执行的结果
System.out.println(t.get());
}
}
class myCallable implements Callable<String>{
@Override
public String call() throws Exception {
return "hh";
}
}
五、定时器
方式一:Timer
public class test {
public static void main(String[] args) throws Exception{
Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("hh");
}
},3000,2000);
}
}
方式二:
public class test {
public static void main(String[] args) throws Exception{
ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("hh");
}
},0,2,TimeUnit.SECONDS);
}
}