Java多线程实现
Java中三种多线程的实现方式。
如果要想在Java中实现多线程有两种途径:
·继承Thread类;
·实现Runnable接口(Callable接口);
继承Thread类
package thread;
//线程操作主类
class MyThread extends Thread//这是一个多线程的操作类
{
private String name ;
public MyThread(String name)
{
this.name = name;
}
@Override
public void run() {//覆写run()方法,作为线程的主体操作方法
for(int x = 1 ; x < 51 ; x++)
{
System.out.println(this.name + "-->"+x);
}
}
}
public class ThreadTest
{
public static void main(String[] args)
{
MyThread mt1 = new MyThread("线程A");
MyThread mt2 = new MyThread("线程B");
MyThread mt3 = new MyThread("线程C");
mt1.start();
mt2.start();
mt3.start();
}
}
结果
线程A-->42
线程A-->43
线程A-->44
线程A-->45
线程A-->46
线程B-->1
线程A-->47
线程B-->2
线程A-->48
线程B-->3
线程A-->49
线程B-->4
线程C-->1
线程C-->2
线程A-->50
线程C-->3
线程C-->4
线程C-->5
疑问?为什么多线程启动不是调用run()方法而是调用start()方法?
看下strat方法定义
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();//线程多次调用时抛出异常
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
}
}
}
private native void start0();
发现在strat方法里面调用了start0()方法,与抽象方法类似,但是使用了native声明。在Java里有JNI技术(Java Native Interface),特点:使用Java调用本机操作系统提供的函数。缺点是不能够离开特定的操作系统。
如果要想线程能够执行,需要操作系统来进行资源分配,所以操作严格来讲主要是由JVM负责根据不同的操作系统而实现的 。
即:使用Thread类的start()方法不仅仅要启动多线程的执行代码,还要去根据不同的操作系统进行资源的分配。
实现Runnable接口
package thread;
class MyThread implements Runnable//这是一个多线程的操作类
{
private String name ;
public MyThread(String name)
{
this.name = name;
}
@Override
public void run() {//覆写run()方法,作为线程的主体操作方法
for(int x = 1 ; x < 51 ; x++)
{
System.out.println(this.name + "-->"+x);
}
}
}
public class ThreadTest
{
public static void main(String[] args)
{
MyThread mt1 = new MyThread("线程A");
MyThread mt2 = new MyThread("线程B");
MyThread mt3 = new MyThread("线程C");
new Thread(mt1).start();
new Thread(mt2).start();
new Thread(mt3).start();
}
}
(面试题)多线程两种实现方式的区别?
·使用Runnable接口与Thread类相比,解决了单继承的定义局限!
·Runnable接口实现的多线程可以比Thread类实现的多线程更加清楚的描述共享的概念。
public class Thread extends Object implements Runnable |
@FunctionalInterface public interface Runnable { public abstract void run(); } |
第三种实现方法:
Runnable接口实现多线程,其中的Run()方法不能返回结果,为了解决这样的矛盾,提供了一个新的接口Callable接口。
Callable接口
Package java.util.concurrent Interface Callable<V> |
@FunctionalInterface public interface Callable<V> { V call() throws Exception; } |
java.util.concurrent Interface Future<V> |
java.util.concurrent.FutureTask<V> public class FutureTask<V> extends Object implements RunnableFuture<V> |
public interface RunnableFuture<V> extends Runnable, Future<V> |
package thread;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
/**
* 使用Callable实现多线程
* 2017-10-07
* @author Junwei Zhu
*
*/
class MyThread02 implements Callable<String>{
private int ticket = 10 ;
@Override
public String call() throws Exception {
for(int x = 0 ; x < 100 ; x ++)
{
if(this.ticket>0)
System.out.println("卖票,ticket:"+this.ticket--);
}
return "票已卖光。" ;
}
}
public class CallableTest {
public static void main(String[] args) throws Exception {
MyThread02 mt1 = new MyThread02();
MyThread02 mt2 = new MyThread02();
//目的是取得call()返回结果
FutureTask<String> task1 = new FutureTask<String>(mt1);
FutureTask<String> task2 = new FutureTask<String>(mt2);
//FutureTask是Runnable接口子类,所以可以使用Thread类的构造来接收task对象
new Thread(task1).start();//启动多线程
new Thread(task2).start();
//多线程执行完毕后可以取得内容,依靠FutureTask中的Future中的get()方法完成
System.out.println("A线程的返回结果:"+task1.get());
System.out.println("B线程的返回结果:"+task2.get());
}
}
结果:
卖票,ticket:10
卖票,ticket:9
卖票,ticket:8
卖票,ticket:8
卖票,ticket:7
卖票,ticket:6
卖票,ticket:7
卖票,ticket:5
卖票,ticket:6
卖票,ticket:5
卖票,ticket:4
卖票,ticket:4
卖票,ticket:3
卖票,ticket:3
卖票,ticket:2
卖票,ticket:1
卖票,ticket:2
A线程的返回结果:票已卖光。
卖票,ticket:1
B线程的返回结果:票已卖光。