Java多线程
基本概念:
进程:程序的一次完整运行
同一个时间点上,会有多个进程轮流抢占资源,但在某个时间点上,只会有一个进程运行;
线程:是进程基础上进一步的划分结果,即:一个进程上可以同时创建多个线程;
线程的存在离不开进程;
java三种多线程实现方式(JDK1.5后增加了第三种):
1:继承Thread类;
2:实现Runnable接口;
3:实现Callable接口。
(1)继承Thread类:
所有程序都有起点main方法,线程同样也有起点,这个起点就是run方法, 在每个线程操作主类里都必须覆写Thread类中提供的run方法;
Public void run(){};
这个方法没有返回值,代表了线程一旦开始就无法结束不能返回内容;
一个简单多线程的例子:
class Mythread extends Thread {
private String name ;
public Mythread (String name) {
this.name = name ;
}
public void run() {
for(int i = 0; i < 200; i++) {
System.out.println(this.name + "--->" + i);
}
}
}
public class 继承Thread类 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Mythread m1 = new Mythread("线程A") ;
Mythread m2 = new Mythread("线程B") ;
Mythread m3 = new Mythread("线程C") ;
m1.start();
m2.start();
m3.start();
}
}
为什么多线程启动不用run(),而用start()?
使用thread类的start()方法不仅要启动多线程,还要根据不同的操作系统进行资源的分配,而且start()方法也调用了run()方法。当执行了start()方法,线程处于就绪状态,执行run()时,线程属于运行状态,直接调用run()方法和执行普通方法没有区别。
- 实现Runnable接口:
因为java单继承的局限性,我们提供Runnable接口,此接口定义如下:
public interface Runnable{
public void run() ;
}
这个run()方法也需要覆写;
任何时候启动多线程都需要用到Thread类里的start()方法,但实现Runnable接口没有srart()方法以供使用。
在Tread类里面定义有如下构造方法:
public Thread(Runnable target);(这代表了可以接受Runnable接口的对象)
class Mythread implements Runnable {
private String name ;
public Mythread (String name) {
this.name = name ;
}
public void run() {
for(int i = 0; i < 200; i++) {
System.out.println(this.name + "--->" + i);
}
}
}
public class 实现Runnable接口 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Mythread m1 = new Mythread("线程A") ;
Mythread m2 = new Mythread("线程B") ;
Mythread m3 = new Mythread("线程C") ;
new Thread(m1).start();
new Thread(m2).start();
new Thread(m3).start();
}
}
多线程的两种实现方式的区别?(面试题)
1:Thread类是Runnable接口的子类(Thread实现了Runnable接口),使用Runnable可以解决单继承的的局限性;
2:Runnable接口实现的多线程可以比Thread类实现的更好的表达数据共享的概念。
(3)Callable接口
为了解决Runnable接口中run()方法没有返回结果的问题,提供了Callable接口。
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
class mythread implements Callable<String>{
private int ticket = 10 ;
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
for(int i = 0; i < 100; i++) {
if(this.ticket > 0) {
System.out.println("卖票:ticket = " + ticket--);
}
}
return "票以卖光!";
}
}
public class 实现Callable接口 {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
mythread m1 = new mythread() ;
mythread m2 = new mythread() ;
FutureTask<String> task1 = new FutureTask<String>(m1) ;
FutureTask<String> task2 = new FutureTask<String>(m2) ;
/*FutureTask是Runnable接口的子类,所以可以使用Thread的构造方法接受它的对象*/
new Thread(task1).start();
new Thread(task2).start();
/*多线程执行完后可以用FutureTask的父接口Future的get()方法取得返回结果*/
System.out.println("1线程的返回结果:" + task1.get());
System.out.println("2线程的返回结果:" + task2.get());
}
}
这个是我在网易云课堂看视频跟老师一起总结的,有问题的可以互相讨论。