《二》多线程基础——Java线程入门类和接口

Java并发编程系列文章
《一》多线程基础——Java线程与进程的基本概念
《二》多线程基础——Java线程入门类和接口
《三》多线程基础——Java线程组和线程优先级
《四》多线程基础——Java线程生命周期及转换
《五》多线程基础——Java线程间的通信(互斥与协作)
《六》实际应用——如何优雅的关闭线程
《七》实际应用——生产者与消费者模型

  并发编程(多线程)一直以来都是程序员头疼的难题。曾经听别人总结过并发编程的第一原则,那就是不要写并发程序,哈哈哈。后来发现,这样能够显著提高程序响应和吞吐量的利器,哪还能忍得住不会用呢?
  整理出《Java并发编程系列文章》,共计7篇,与君共勉。


《二》多线程基础——Java线程入门类和接口


1、Thread

  JDK提供了Thread 类来让我们实现⾃⼰的“线程”类:继承 Thread 类,并重写 run ⽅法。

public class Demo {
    public static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("MyThread");
        }
    }
    public static void main(String[] args) {
        Thread myThread = new MyThread();
        myThread.start();
    }
}

  调⽤start()后,虚拟机会先为我们创建⼀个线程,然后等到这个线程第⼀次得到时间片时再调⽤run()⽅法。多次调⽤start()⽅法,程序会抛出异常。

Thread类的⼏个常⽤的⽅法:
currentThread():静态⽅法,返回对当前正在执⾏的线程对象的引⽤;
start():开始执⾏线程的⽅法,java虚拟机会调⽤线程内的run()⽅法;
yield():yield在英语⾥有放弃的意思,同样,这⾥的yield()指的是当前线程愿
意让出对当前处理器的占⽤。这⾥需要注意的是,就算当前线程调⽤了yield() ⽅法,程序在调度的时候,也还有可能继续运⾏这个线程的;
sleep():静态⽅法,使当前线程睡眠⼀段时间;
join():使当前线程等待另⼀个线程执⾏完毕之后再继续执⾏,内部调⽤的是
Object类的wait⽅法实现的;

2、Runnable

  JDK提供了 Runnalble 接⼝来让我们实现⾃⼰的“线程”类:实现 Runnable 接⼝的 run ⽅法。

public class Demo {
    public static class MyThread implements Runnable {
        @Override
        public void run() {
            System.out.println("MyThread");
        }
    }
    public static void main(String[] args) {
        new Thread(new MyThread()).start();
    }
}

  Runnable只是一个函数式接口,源码如下。Thread 类是⼀个 Runnable 接⼝的实现类,源码如下。
  它们是策略模式的一个经典应用。什么是策略模式?看这里。在这个策略模式中,Runnable 接⼝作为策略接口Thread 类作为逻辑类Thread中添加一个成员变量target用于保存对于Runnable实现类对象的引用。 然后通过构造方法以修改该成员变量。 通过传入不同的Runnable实现类对象,即可将控制逻辑,与具体任务单元抽离开。

/**
Runnable源码
*/
@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

/**
Thread源码片段
*/
public class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }

    private volatile String name;
    private int            priority;
    private Thread         threadQ;
    private long           eetop;

    /* Whether or not to single_step this thread. */
    private boolean     single_step;
    /* Whether or not the thread is a daemon thread. */
    private boolean     daemon = false;
    /* JVM state */
    private boolean     stillborn = false;
    /* What will be run. */
    private Runnable target;
    ......

3、Callable、Future与FutureTask

  通常来说,我们使⽤ RunnableThread 来创建⼀个新的线程。但是它们有⼀个弊端,就是 run⽅法是没有返回值的。⽽有时候我们希望开启⼀个线程去执⾏⼀个任务,并且这个任务执⾏完成后有⼀个返回值。JDK提供了 Callable接⼝Future类为我们解决这个问题,这也是所谓的异步模型
  CallableRunnable 类似,同样是只有⼀个抽象⽅法的函数式接⼝。不同的是, Callable 提供的⽅法是有返回值的,⽽且⽀持泛型。

@FunctionalInterface
public interface Callable<V> {
    V call() throws Exception;
}

  一般来说,Callable都是配合线程池工具ExecutorService 一起用的,利用ExecutorService 可以使⽤ submit ()来让⼀个 Callable 接⼝执⾏。它会返⼀个 Future ,可以通过这个 Futureget ()得到结果。
  这⾥可以看⼀个简单的使⽤demo:

// ⾃定义Callable
class Task implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        // 模拟计算需要⼀秒
        Thread.sleep(1000);
        return 2;
    }
    public static void main(String args[]){
        // 使⽤
        ExecutorService executor = Executors.newCachedThreadPool();
        Task task = new Task();
        Future<Integer> result = executor.submit(task);
        // 注意调⽤get⽅法会阻塞当前线程,直到得到结果。
        // 所以实际编码中建议使⽤可以设置超时时间的重载get⽅法。
        System.out.println(result.get());
    }
}

输出:
2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值