一.进程与线程
进程:是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位
线程:是进程中的一个执行路径,是cpu分配的基本单位。一个进程最少拥有一个线程。
二. Java多线程的创建及启动
1.继承Thread类
优点获取当前线程简单直接使用this即可,缺点java不支持多继承,继承了Thread就无法继承其他类了。
public class MyThread extends Thread {
private int i = 0;
@Override
public void run() {
for (i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
public class ThreadTest {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 30) {
// 创建一个新的线程 myThread1 此线程进入新建状态
Thread myThread1 = new MyThread();
// 创建一个新的线程 myThread2 此线程进入新建状态
Thread myThread2 = new MyThread();
// 调用start()方法使得线程进入就绪状态
myThread1.start();
// 调用start()方法使得线程进入就绪状态
myThread2.start();
}
}
}
}
2.实现Runnable接口
优点接口可以多实现,减少耦合
public class MyRunnable implements Runnable {
private int i = 0;
@Override
public void run() {
for (i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
public class ThreadTest {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 30) {
// 创建一个Runnable实现类的对象
Runnable myRunnable = new MyRunnable();
// 将myRunnable作为Thread target创建新的线程
Thread thread1 = new Thread(myRunnable);
Thread thread2 = new Thread(myRunnable);
// 调用start()方法使得线程进入就绪状态
thread1.start();
thread2.start();
}
}
}
}
说明: 继承Thread类与实现Runnable接口创建线程方式相似,不同的地方在于,因为Thread类本身也是实现了Runnable接口。
/**Thread类中对Runnable接口中run()方法的实现*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
也就是说,当执行到Thread类中的run()方法时,会首先判断target是否存在,存在则执行target中的run()方法,也就是实现了Runnable接口并重写了run()方法的类中的run()方法
3.使用Callable接口和FutureTask类创建线程
优点是具有返回值
public class MyCallable implements Callable<Integer> {
private int i = 0;
// 与run()方法不同的是,call()方法具有返回值
@Override
public Integer call() {
int sum = 0;
for (; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
sum += i;
}
return sum;
}
}
public class ThreadTest {
public static void main(String[] args) {
// 创建MyCallable对象
Callable<Integer> myCallable = new MyCallable();
// 使用FutureTask来包装MyCallable对象
FutureTask<Integer> ft = new FutureTask<Integer>(myCallable);
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 30) {
// FutureTask对象作为Thread对象的target创建新的线程
Thread thread = new Thread(ft);
// 线程进入到就绪状态
thread.start();
}
}
System.out.println("主线程for循环执行完毕..");
try {
// 取得新创建的新线程中的call()方法返回的结果
int sum = ft.get();
System.out.println("sum = " + sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
需要特别注意的是:不能对同一线程对象两次调用start()方法。原因是threadStatus的在一次调用后值就变化了,再次进入的时候通过判断threadStatus的值从而产生异常。