在Java中,多线程主要的实现方式有四种:继承Thread类、实现Runnable接口、实现Callable接口通过FutureTask包装器来创建Thread线程、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,而后两种是带返回值的。除此之外,通过Timer启动定时任务,或者通过像Spring Task和quartz这样的第三方任务调度框架也可以开启多线程任务。
什么是进程?什么是线程?
进程是:一个应用程序(1个进程是一个软件)。
线程是:一个进程中的执行场景/执行单元。
注意:一个进程可以启动多个线程。
对于java程序来说,当在DOS命令窗口中输入:
java HelloWorld 回车之后。会先启动JVM,而JVM就是一个进程。
JVM再启动一个主线程调用main方法(main方法就是主线程)。
同时再启动一个垃圾回收线程负责看护,回收垃圾。
最起码,现在的java程序中至少有两个线程并发,一个是 垃圾回收线程,一个是 执行main方法的主线程。
进程和线程是什么关系?
进程:可以看做是现实生活当中的公司。
线程:可以看做是公司当中的某个员工。
注意:
进程A和进程B的 内存独立不共享
。
魔兽游戏是一个进程
酷狗音乐是一个进程
这两个进程是独立的,不共享资源。
线程并发
1线程执行t1的。
t2线程执行t2的。t1不会影响t2,t2也不会影响t1
继承Thread类创建线程
Thread类的构造方法
Thread类本质上也是实现了Runnable接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程比较简单,通过继承Thread类并复写run()方法,就可以启动新线程并执行自己定义的run()方法。
CreateThreadDemo1.java
public class CreateThreadDemo1 extends Thread {
public CreateThreadDemo1(String name) {
// 设置当前线程的名字
this.setName(name);
}
@Override
public void run() {
System.out.println("当前运行的线程名为: " + Thread.currentThread().getName());
}
public static void main(String[] args) throws Exception {
// 注意这里,要调用start方法才能启动线程,不能调用run方法
new CreateThreadDemo1("MyThread1").start();
new CreateThreadDemo1("MyThread2").start();
}
}
运行结果:
当前运行的线程名为: MyThread1
当前运行的线程名为: MyThread2
Runnable接口简介
(1)定义
Runnable接口是线程辅助类,仅定义了一个方法run()方法
(2)作用
实现多线程
(3)优点
灵活:Runnable可以继承其他类实现对Runnable实现类的增强,避免了Thread类由于继承Thread类而无法继承其他类的问题
共享资源:Runnable接口的run()方法可以被多个线程共享,适用于多个进程处理一种资源的问题
实现Runnable接口来创建并启动线程的步骤如下:
1 定义Runnable接口的实现类,重写该接口的run()方法,该run()方法的方法体是该线程的线程执行体。
2 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
3 调用线程对象的start()方法来启动该线程。
// 通过实现Runnable接口来创建线程类
public class SecondThread implements Runnable
{
private int i ;
// run方法同样是线程执行体
public void run()
{
for ( ; i < 100 ; i++ )
{
// 当线程类实现Runnable接口时,
// 如果想获取当前线程,只能用Thread.currentThread()方法。
System.out.println(Thread.currentThread().getName()
+ " " + i);
}
}
public static void main(String[] args)
{
for (int i = 0; i < 100; i++)
{
System.out.println(Thread.currentThread().getName()
+ " " + i);
if (i == 20)
{
SecondThread st = new SecondThread(); // ①
// 通过new Thread(target , name)方法创建新线程
new Thread(st , "新线程1").start();
new Thread(st , "新线程2").start();
}
}
}
}
运行后:
......
main 17
main 18
main 19
main 20
main 21
main 22
main 23
main 24
main 25
main 26
新线程2 0
main 27
新线程1 0
新线程1 2
main 28
新线程2 1
main 29
新线程1 3
main 30
新线程2 4
main 31
新线程1 5
main 32
......