多线程总结--2:怎样实现多线程?

怎样实现多线程?

实现多线程的方式有3种:

  1. 继承Thread类:Thread类中有一个run方法,覆写run方法,运行线程要调用Thread类的start方法。实际上Thread类中的run方法也是覆写的;
    在这里插入图片描述在这里插入图片描述
  2. 实现Runnable接口:继承Thread类有单继承的缺陷,Thread类本身也实现了Runnable接口,所以实现Runnable接口让代码更加灵活,并且实现Runnable接口可以更好的实现程序共享的概念;
    在这里插入图片描述
  3. 实现Callable接口,覆写call():V方法;
    在JDK1.5新加了开发包:java.uti.concurrent;这个包主要是用于高并发编程使用,Callable接口就是这里的。在Runnable里的run方法没有返回值,某些线程在结束时可能会带回一些返回结果,这个时候就可以用Callable接口里的call方法,call方法的返回值需要Future接口里的get():V方法来接收,现在我们来看看这些方法的内部结构,这里涉及到了Future接口,FutureTask类,Runnable接口,Thread类,RunnableFuture接口,Callable接口,以及一个自己定义的类Mythread;
    在这里插入图片描述
    看一下源码:
    FutureTask类实现了RunnableFuture接口
    在这里插入图片描述
    RunnableFuture接口则继承了Runnable接口和Future接口,得到run方法和get方法
    在这里插入图片描述
    Thread类实现了Runnable接口,也有run方法,下面来看一下使用Callable接口实现多线程的例子:
package TestThread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
class TestCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        int tikle = 20;
        for (int i = 0; i < 20; i++) {
            System.out.println("当前线程:"+Thread.currentThread().getName()+"剩余"+tikle--+"票");
        }
        return "票卖完了";
    }
}
public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCallable tc1 = new TestCallable();
        FutureTask ft1 = new FutureTask(tc1);
        Thread thread = new Thread(ft1);
        Thread thread1 = new Thread(ft1);
        Thread thread2 = new Thread(ft1);
        thread.start();
        thread1.start();
        thread2.start();
        System.out.println(ft1.get());
    }
}

看一下运行结果:
在这里插入图片描述
程序中已经说明了Callable接口是如何实现多线程的,实例化一个Callable对象,传给FurtherTask构造,得到一个任务,然后用任务调用三个线程,这个过程是使用Callable接口的内部结构决定的,不懂的再去看看结构图。

但是从结果上来看,只有一个线程在工作,细心的人可以发现,只创建了一个FutureTask,这时候你就会想这会不会是因为只有一个FutureTask所以才只调用了一个线程呢,实际上FutureTask可以保证多线程场景下,任务只会被一个线程执行一次,其他线程不再执行此任务,那么任务是什么呢,MyThread的对象就是一个任务,一个任务在FutureTask的分配下只能有一个线程执行一次,呢么怎么调用多个线程来执行任务呢,我们将任务分配给多个FutureTask,就相当于备份了多个任务,这样就可以调用多个线程来执行了,代码及结果如图:

package TestThread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
class TestCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        int tikle = 10;
        for (int i = 0; i < 10; i++) {
            System.out.println("当前线程:"+Thread.currentThread().getName()+"剩余"+tikle--+"票");
        }
        return "票卖完了";
    }
}
public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCallable tc1 = new TestCallable();
        FutureTask ft1 = new FutureTask(tc1);
        FutureTask ft2 = new FutureTask(tc1);
        FutureTask ft3 = new FutureTask(tc1);
        Thread thread1 = new Thread(ft1,"A");
        Thread thread2 = new Thread(ft2,"B");
        Thread thread3 = new Thread(ft3,"C");
        thread1.start();
        System.out.println(ft1.get());
        thread2.start();
        System.out.println(ft2.get());
        thread3.start();
        System.out.println(ft3.get());
    }
}

结果(此处已实验过10000张票,结果相同,此处为容易观看,减少次数):

当前线程:A剩余10票
当前线程:A剩余9票
当前线程:A剩余8票
当前线程:A剩余7票
当前线程:A剩余6票
当前线程:A剩余5票
当前线程:A剩余4票
当前线程:A剩余3票
当前线程:A剩余2票
当前线程:A剩余1票
票卖完了
当前线程:B剩余10票
当前线程:B剩余9票
当前线程:B剩余8票
当前线程:B剩余7票
当前线程:B剩余6票
当前线程:B剩余5票
当前线程:B剩余4票
当前线程:B剩余3票
当前线程:B剩余2票
当前线程:B剩余1票
票卖完了
当前线程:C剩余10票
当前线程:C剩余9票
当前线程:C剩余8票
当前线程:C剩余7票
当前线程:C剩余6票
当前线程:C剩余5票
当前线程:C剩余4票
当前线程:C剩余3票
当前线程:C剩余2票
当前线程:C剩余1票
票卖完了
Process finished with exit code 0

你看了结果会发现确实不是一个线程执行任务了,但是多个线程并没有并发执行呀,又出错了,出错了没关系,如果你知道这么一个概念:Future接口中的get()方法会阻塞当前线程直到取得Callable的返回值,现在你就应该知道为什么线程没有并发执行,我们修改一下代码试试,我们把三行get方法的代码注释掉,看看结果(只截取一部分结果):

当前线程:C剩余42票
当前线程:C剩余41票
当前线程:C剩余40票
当前线程:B剩余17票
当前线程:A剩余23票
当前线程:A剩余22票
当前线程:A剩余21票
当前线程:A剩余20票
当前线程:B剩余16票
当前线程:C剩余39票
当前线程:C剩余38票
当前线程:C剩余37票
当前线程:C剩余36

可以看到线程的交替执行,这已经说明了线程是并发的了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值