美文网首页
Java多线程[集成thread, 实现Runnable, 实现

Java多线程[集成thread, 实现Runnable, 实现

作者: Phoebe_Liu | 来源:发表于2018-10-24 15:47 被阅读0次

一、 实现Runnable 接口,并实现该接口的 run() 方法。

  • 通过实现Runnable接口的类,就是产生一个任务或者工作类,交给一个或者多个线程去完成这个任务(new Thread(任务).start()).
  • 资源共享
  • start()方法是一个 native(本地)方法,它将启动一个新线程,并执行 run()方法
public class ThreadTask implements Runnable {
 
  private int ticket = 10;
  public void run() {
    for (int i = 0; i < 10; i++) {
      if (this.ticket > 0) {
        try {
          Thread.sleep(100);
          System.out.println(Thread.currentThread().getName() + "---卖票:ticket:" + (ticket--));
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }
  public static void main(String[] args) {
    ThreadTask thread = new ThreadTask();
    new Thread(thread, "线程1").start();
    new Thread(thread, "线程2").start();
  }
}
线程2---卖票:ticket:10
线程1---卖票:ticket:9
线程1---卖票:ticket:8
线程2---卖票:ticket:7
线程2---卖票:ticket:6
线程1---卖票:ticket:5
线程1---卖票:ticket:4
线程2---卖票:ticket:3
线程1---卖票:ticket:2
线程2---卖票:ticket:1
线程1---卖票:ticket:0

二、 继承 Thread 类,重写 run 方法

public class ThreadTask extends Thread {
  private int ticket = 10;
 
  public void run() {
    for (int i = 0; i < 10; i++) {
      if (this.ticket > 0) {
        try {
          Thread.sleep(100);
          System.out.println(Thread.currentThread().getName() + "---卖票:ticket:" + (ticket--));
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }
  public static void main(String[] args) {
    ThreadTask task = new ThreadTask();
    new Thread(task,"线程1").start();
    new Thread(task,"线程2").start();
  }
}
Thread-1---卖票:ticket:10
Thread-0---卖票:ticket:10
Thread-1---卖票:ticket:9
Thread-0---卖票:ticket:9
Thread-1---卖票:ticket:8
Thread-0---卖票:ticket:8
Thread-1---卖票:ticket:7
Thread-0---卖票:ticket:7
Thread-1---卖票:ticket:6
Thread-0---卖票:ticket:6
Thread-1---卖票:ticket:5
Thread-0---卖票:ticket:5
Thread-0---卖票:ticket:4
Thread-1---卖票:ticket:4
Thread-1---卖票:ticket:3
Thread-0---卖票:ticket:3
Thread-1---卖票:ticket:2
Thread-0---卖票:ticket:2
Thread-1---卖票:ticket:1
Thread-0---卖票:ticket:1
  • 前面这两种方式,当遇到运行时异常(非受检异常, RuntimeException)时,会导致子线程被JVM杀死 子线程结束,但不会影响到主线程。
  • 主线程通过setUncaughtExceptionHandler(Thread.UncaughtExceptionHandlereh)方法用来获取线程中产生的异常.
import java.lang.Thread.UncaughtExceptionHandler;
 
public class ThreadTest1 {
 
    public static void main(String[] args) {
        MyThread my = new MyThread();
        my.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println(t.getName() + " : " + e.getMessage());
            }
        });
        try {
            my.start();
        } catch (Exception e) {
            System.out.println("error");
        }
    }
    
    public static class  MyThread extends Thread {
        public MyThread() {}
        public void run() {
            for (int i = 4; i >= 0; i--) {
                    TimeUnit.SECONDS.sleep(1);
                    // 当i=0时候抛出的非受检异常,将导致当前线程被JVM杀死
                    System.out.println(12 / i);
                }
    }
}

三、 实现Callable<T>,重写call()方法。

  • 异步执行,Future 对象表示异步计算的结果;当调用 Future 的 get()方法以获取结果时,当前线程就会阻塞,直到 call()方法结束返回结果。
  • 运行Callable任务可拿到一个Future对象, Future表示异步计算的结果。
  • 可通过FutureTask或者ExecutorServor包装
  • call()方法可抛出异常,而run()方法是不能抛出异常的
  • 在提交任务时,用户实现的Callable实例task会被包装为FutureTask实例ftask;提交后任务异步执行,无需用户关心;当用户需要时,再调用FutureTask#get()获取结果——或异常。

1. 通过FutureTask包装器来创建Thread线程

public class ThreadByCallable implements Callable<Integer> {
    
    @Override
    public Integer call() {
        System.out.println("当前线程名称是:" + Thread.currentThread().getName());

        int i = 0;
        for (; i < 5; i++) {
            System.out.println("循环变量i的值:" + i);
        }
        
        // call()方法有返回值
        return i;
    }

    public static void main(String[] args) {
        ThreadByCallable rt = new ThreadByCallable();

        // 使用FutureTask来包装Callable对象
        FutureTask<Integer> task = new FutureTask<Integer>(rt);
        new Thread(task, "有返回值的线程").start();
        try {
            // 获取线程返回值
            System.out.println("子线程的返回值:" + task.get());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

2. 通过线程池

public class CallableAndFuture {

    public static class CallableTest implements Callable<String> {
        public String call() throws Exception {
            return "Hello World!";
        }
    }

    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newSingleThreadExecutor();

        Future<String> future = threadPool.submit(new CallableTest());
        try {
            System.out.println("waiting thread to finish");
            System.out.println(future.get()); //等待线程结束,并获取返回结果
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

相关文章

  • Java多线程面试题整理--持续更新

    一 用Runnable还是Thread? Java中实现多线程有两种方法:继承Thread类、实现Runnable...

  • 两种建立多线程的方式

    Thread和Runnable实现多线程的区别 Java中实现多线程有两种方法:继承Thread、实现Runnab...

  • 3-Java中如何创建线程

    Runnable和Thread实现多线程的区别 Java中实现多线程有两种方法:继承Thread类、实现Runna...

  • Thread,Runnable和Callable

    Java多线程实现方式:Thread,Runnable,Callable多线程是乱序执行Thread===1.Th...

  • java多线程

    1.JAVA多线程实现方式 JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用E...

  • Q&A-04 多线程&分布式

    1、Java实现多线程有哪几种方式 Java 多线程实现方式主要有四种: 继承Thread类 实现Runnable...

  • Java多线程理解1

    Java实现多线程的两种方式分别是继承Thread类和实现Runnable接口。 继承Thread类 实现Runn...

  • Java多线程[集成thread, 实现Runnable, 实现

    一、 实现Runnable 接口,并实现该接口的 run() 方法。 通过实现Runnable接口的类,就是产生一...

  • Thread的使用说明

    前言 Java当中实现多线程的方法主要有两种方式:集成Thread类和实现Runnable接口定义线程的运行时行为...

  • 多线程(最全面试题04)

    Java实现线程有哪几种方式?1、继承Thread类实现多线程2、实现Runnable接口方式实现多线程3、使用E...

网友评论

      本文标题:Java多线程[集成thread, 实现Runnable, 实现

      本文链接:https://www.haomeiwen.com/subject/fxqxtqtx.html