首页 > 编程语言 > 详细

多线程

时间:2021-04-28 16:45:27      阅读:31      评论:0      收藏:0      [点我收藏+]

线程创建、start、run

一、创建线程方式

 java创建线程的方式,主要有三种:类Thread接口Runnable接口Callable

1、Thread和Runnable进行比较

他们之间的区别

 1、实现Runnable的类更具有健壮性,避免了单继承的局限。

 2、Runnable更容易实现资源共享,能多个线程同时处理一个资源。

不过对于共享数据而言,使用继承Thread,同样可以实现多线程同时处理同一个资源。

(1)像网上常写的这种方式当然不能实现共享资源了,因为你已经new了多个对象,每个对象之前当然不共享数据

class PrintNum extends Thread{
    public void run(){
        //子线程执行的代码
        for(int i = 1;i <= 100;i++){
            if(i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}


public class TestThread {
    public static void main(String[] args) {
        PrintNum p1 = new PrintNum("线程1");
        PrintNum p2 = new PrintNum("线程2"); 
        p1.start();
        p2.start();
    }
}

 (2)但如果你只new一个对象,难道不能实现多线程吗?其实也是可以的,看如下代码:

public class TicketThread extends Thread{

    private int ticket = 10;

    public void run(){
        for(int i =0;i<10;i++){
            //首先主要这个this关键字代表当前对象,而下面因为我只new了TicketThread t1 = new TicketThread();一个对象
            //所以这个锁是没有问题,但如果new多个的话用this锁同样会失效,为了安全我们可以用TicketThread.class
            synchronized (this){
                if(this.ticket>0){
                    try {
                        Thread.sleep(100);
                        System.out.println(Thread.currentThread().getName()+"卖票---->"+(this.ticket--));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } } } 
            }}

    public static void main(String[] arg){
        TicketThread t1 = new TicketThread();
        new Thread(t1,"线程1").start();
        new Thread(t1,"线程2").start();
        //经常看到晚上说thread不能共享资源,这个用例子说明thread同样可以共享资源。
        //为什么它也能共享呢?因为Thread本来就是实现了Runnable,包含Runnable的功能是很正常。
    }
}

2、Runnable和Callable区别

两者最大的不同点是:

(1)实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;

(2)Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;

举一个Callable获得返回值小案例

public class CallableImpl implements Callable<String> {

    public CallableImpl(String acceptStr) {
        this.acceptStr = acceptStr;
    }
    private String acceptStr;
   //Callable是重写call方法
    @Override
    public String call() throws Exception {
        // 任务阻塞 1 秒
        Thread.sleep(1000);
        return this.acceptStr + " append some chars and return it!";
    }


    public static void main(String[] args) throws ExecutionException, InterruptedException {
     //Callable对象实现线程,需要先把对象放入FutureTask对象中,再把FutureTask对象放入Thread对象中
        Callable<String> callable = new CallableImpl("my callable test!");
        FutureTask<String> task = new FutureTask<>(callable);
        long beginTime = System.currentTimeMillis();
        // 创建线程
        new Thread(task).start();
        // 调用get()阻塞主线程,反之,线程不会阻塞
        String result = task.get();
        long endTime = System.currentTimeMillis();
        System.out.println("hello : " + result);
        System.out.println("cast : " + (endTime - beginTime) / 1000 + " second!");
    }
}
/**
 * 运行结果
 * hello : my callable test! append some chars and return it!
 * cast : 1 second!
 */

 

多线程

原文:https://www.cnblogs.com/javacd/p/14714110.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!