java多线程实现表复制_Java多线程的三种实现方式
今天简单说一下Java三种多线程实现方式和区别,主要有实现Runnable、Callable和继承Thread三种方式。
实现Runnable的方式
这种方式比较常用,当我们的线程类有继承其他的类的情况下(Java不支持类多继承),并且线程任务不需要返回值的情况下可以选用这种方式。
public class ThreadRunnableDemo implementsRunnable{
/**计数变量*/
private int count = 0;
public static void main(String[] args) throwsInterruptedException {
ThreadRunnableDemo threadRunnableDemo = newThreadRunnableDemo();
//实例化线程
Thread thread = new Thread(threadRunnableDemo, "threadRunnableDemoA"); System.out.println(String.format("线程状态preStart: %s", thread.getState()));
//启动线程
thread.start(); System.out.println(String.format("线程状态afterStart: %s", thread.getState()));
//主线程休眠1000ms
Thread.sleep(1000); System.out.println(String.format("线程状态after1000ms: %s", thread.getState()));
}
@Override public voidrun() {
count++;
System.out.println(String.format("线程名称:%s, 线程状态:%s, count:%s", Thread.currentThread().getName(), Thread.currentThread().getState(), count));
} }
输出结果:
线程状态preStart: NEW 线程状态afterStart: RUNNABLE 线程名称:threadRunnableDemoA, 线程状态:RUNNABLE, count:1
线程状态after1000ms: TERMINATED
实现Callable的方式
当我们执行线程需要返回值的时候那么就必须选用实现Callable类的方式,因为目前只有这种方式能返回值。当然这种方式我们也可以不需要获取返回值。
这种方式是通过FutureTask的get()方法(下面代码的第22行)或者get(long timeout, TimeUnit unit)(下面代码的第28行)方法获取返回值。当我们看Callable的接口定义的源码会发现“public interface Callable ” ,我们实现的时候是需要定义返回类型,如下面代码所示。
除此之外我们还需要注意的是:当我们通过FutureTask的get()方法去获取线程的返回值的时候是要等到线程call()内容都执行完毕之后才能获取得到,并且get()方法后面的代码必须等待,说明这一定是同步的,所以我们可以在真正需要线程返回值的时候才通过get()方法去获取,以免被阻塞。当我们通过get(long timeout, TimeUnit unit)方式去获取的时候可以设置超时时间,如果超过所设置的超时时间都没有获取到线程返回的值则会抛出 java.util.concurrent.TimeoutException 异常,当然如果在get(long timeout, TimeUnit unit)之前用get()方式获取了的话就不会抛异常。
实现Callable还有个好处就是可以线程可以抛异常,如果我们需要在线程里抛出异常的话也可以选用这种方式,其他两种方式只能捕获异常信息。
public class ThreadCallableDemo implements Callable{
/**计数变量*/
private int count = 0;
public static void main(String[] args) throwsInterruptedException, ExecutionException, TimeoutException {
ThreadCallableDemo threadCallableDemo = newThreadCallableDemo();
//通过FutureTask获取返回值
FutureTask taskA = new FutureTask<>(threadCallableDemo);
//实例化线程
Thread thread = new Thread(taskA, "threadCallableDemoA"); System.out.println(String.format("线程状态preStart: %s", thread.getState()));
//启动线程
thread.start(); System.out.println(String.format("线程状态afterStart: %s", thread.getState()));
//通过FutureTask的get()方法获取返回值
int result =taskA.get(); System.out.println("是否同步测试...."); System.out.println(String.format("result: %s", result)); System.out.println(String.format("线程状态afterGetResult1: %s", thread.getState()));
//通过FutureTask的get()方法获取返回值 设置超时时间 单位为ms
int resultWithTime = taskA.get(100, TimeUnit.MILLISECONDS); System.out.println(String.format("resultWithTime: %s", resultWithTime)); System.out.println(String.format("线程状态afterGetResult2: %s", thread.getState()));
}
/**
* 实现Callable的call类 */
@Override public Integer call() throwsException {
//自增
count++;
System.out.println(String.format("线程名称:%s, 线程状态:%s, count:%s", Thread.currentThread().getName(), Thread.currentThread().getState(), count)); System.out.println("休眠1000ms...."); Thread.currentThread().sleep(1000);
returncount; } }
输出结果:
线程状态preStart: NEW 线程状态afterStart: RUNNABLE 线程名称:threadCallableDemoA, 线程状态:RUNNABLE, count:1
休眠1000ms.... 是否同步测试.... result: 1
线程状态afterGetResult1: TERMINATED resultWithTime: 1
线程状态afterGetResult2: TERMINATED
继承Thread的方式
Thread类实际上也是实现Runnable接口,所以当我们继承Thread的时候我们即使不实现run()方法也不会报错,这种方式也经常用。
下面我写了两种不同继承Thread的代码,大家可以看一下区别,我在网上看到很多人说 继承Thread实现多线程,线程间不能共享数据,但是我用下面的代码1方式似乎也可以共享哇,欢迎大家提出质疑。
代码1:
public class ThreadThreadDemo extendsThread{
/**计数变量*/
private int count = 0;
public static void main(String[] args) throwsInterruptedException {
ThreadThreadDemo threadThreadDemo = newThreadThreadDemo();
//实例化线程
Thread thread = new Thread(threadThreadDemo, "threadThreadDemoA"); System.out.println(String.format("线程状态preStart: %s", thread.getState()));
//启动线程
thread.start(); System.out.println(String.format("线程状态afterStart: %s", thread.getState()));
//主线程休眠1000s
Thread.sleep(1000); System.out.println(String.format("线程状态after1000ms: %s", thread.getState())); }
@Override public voidrun() {
count++;
System.out.println(String.format("线程名称:%s, 线程状态:%s, count:%s", Thread.currentThread().getName(), Thread.currentThread().getState(), count)); } }
输出结果1:
线程状态preStart: NEW 线程状态afterStart: RUNNABLE 线程名称:threadThreadDemoA, 线程状态:RUNNABLE, count:1
线程状态after1000ms: TERMINATED
代码2:
public class ThreadThreadDemo extendsThread{
/**计数变量*/
private int count = 0;
public static void main(String[] args) throwsInterruptedException {
ThreadThreadDemo threadThreadDemo = newThreadThreadDemo();
//实例化线程
System.out.println(String.format("线程状态preStart: %s", threadThreadDemo.getState()));
//启动线程
threadThreadDemo.start(); System.out.println(String.format("线程状态afterStart: %s", threadThreadDemo.getState()));
//主线程休眠1000s
Thread.sleep(1000); System.out.println(String.format("线程状态after1000ms: %s", threadThreadDemo.getState())); }
@Override public voidrun() {
count++;
System.out.println(String.format("线程名称:%s, 线程状态:%s, count:%s", Thread.currentThread().getName(), Thread.currentThread().getState(), count)); } }
输出结果2:
线程状态preStart: NEW 线程状态afterStart: RUNNABLE 线程名称:Thread-0, 线程状态:RUNNABLE, count:1
线程状态after1000ms: TERMINATED
最后总结:
如果不要求线程返回结果,也不需要抛异常也没有继承其他的类,那么三种方式可以任选,看喜好;
如果有继承其他类,那么就只能用实现Runnable和实现Callable的方式;
如果需要线程返回结果或者需要线程抛异常那么选择实现Callable的方式的方式,但是需要注意的是获取返回结果是同步的方式。
如果有疑问或者有问题欢迎留言讨论!
总结
以上是生活随笔为你收集整理的java多线程实现表复制_Java多线程的三种实现方式的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: python数字列表in_Python入
- 下一篇: Java指派问题_指派问题的匈牙利算法