进程
是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间
线程
是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行. 一个进程最少有一个线程.线程实际上是在进程基础之上的进一步划分,一个进程启动之后,里面的若干执行路径又可以划分成若干个线程.
同步:排队执行 , 效率低但是安全.
异步:同时执行 , 效率高但是数据不安全.
因此,在很多实际开发中我们要用到多线程技术,我们需要知道如何在Java中创建多线程.
Java中多线程的几种创建方式:1.继承Thread类,重写run方法
public class TestThread {
public static void main(String[] args) {
Thread thread = new MyThread();
thread.start();
for (int i = 0 ; i<100;i++){
System.out.println(Thread.currentThread().getName()+"正在打印数字:"+i);
}
}
public static class MyThread extends Thread{
@Override
public void run() {
for (int i = 0 ; i<100;i++){
System.out.println(Thread.currentThread().getName()+"正在打印数字:"+i);
}
}
}
}
2.使用Thread类的有参构造函数,把Runnable接口的实现类作为构造器的参数
public class TestThread {
public static void main(String[] args) {
Runnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
for (int i = 0 ; i<100;i++){
System.out.println(Thread.currentThread().getName()+"正在打印数字:"+i);
}
}
public static class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0 ; i<100;i++){
System.out.println(Thread.currentThread().getName()+"正在打印数字:"+i);
}
}
}
}
需要注意的是无论是第一种方法还是第二种方法,创建线程后调用的都是start方法,而非重写的run方法3利用FutureTask和Callable实现多线程
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class TestThread {
public static void main(String[] args) {
Callable callable = new MyCallable();
FutureTask futureTask = new FutureTask<>(callable);
new Thread(futureTask).start();
for (int i = 0 ; i<100;i++){
System.out.println(Thread.currentThread().getName()+"正在打印数字:"+i);
}
}
public static class MyCallable implements Callable {
@Override
public Integer call() throws Exception {
for (int i = 0 ; i<100;i++){
System.out.println(Thread.currentThread().getName()+"正在打印数字:"+i);
}
return -1;
}
}
}
Runnable 与 Callable的相同点
都是接口
都可以编写多线程程序
都采用Thread.start()启动线程
Runnable 与 Callable的不同点
Runnable没有返回值;Callable可以返回执行结果
Callable接口的call()允许抛出异常;Runnable的run()不能抛出
Callable获取返回值
Callalble接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞主进程的继续往下执行,如果不调用不会阻塞。



