Java再学习——线程之创建

Java创建线程有两种方法,一种是继承Thread,另一种实现Runnable或Callable接口。

一,继承Thread

public class APP {

    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                int i = 0;
                while (i < 100) {
                    System.out.println(i++);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        thread.start();
    }
}

上述例子通过重写Thread的run方法,来定时输出i的值,但是要主要Thread的run方法仅仅是个普通的方法,必须要通过调用start方法才能创建线程去执行run方法,直接调用run就没有线程的创建了。

二,实现Runnable或Callable接口来创建线程。

这两个接口的实现只能是变成一个普通的类,要创建线程都必须要通过其他相关类开启的。

这两个接口最大的区别:Callable有返回值且能抛出受检测异常,而Runnable没有返回值也无法抛出受检测异常;

1,对于Runnable接口来说,

  要通过它来创建线程的的方法有两种,一种是通过Thread,另一种是通过Executor

public class APP {

    public static void main(String[] args) {

        class MyRunnable implements Runnable {
            @Override
            public void run() {
                System.out.println("start -> "
                        + Thread.currentThread().getName());
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("end -> " + Thread.currentThread().getName());
            }

        }

        Thread thread = new Thread(new MyRunnable());
        thread.start();

        Executor executor = Executors.newSingleThreadExecutor();
        executor.execute(new MyRunnable());
    }
}

2,对于Callable接口来说,

  要通过它来创建线程的的方法有两种,一种是通过Thread,另一种是通过ExecutorService,但是都要同时借助于Future接口来实现对Callable返回值的相关控制。这里的ExecutorService接口是继承了Executor接口的,它增加了一些功能,大家可以点开源码看看就知道,而实例化都是通过Executors类的静态方法来实现的。

2.1 通过Thread去创建

  由于Thread只能接受Runnable所以要想通过Thread去创建Callable线程,还要再借助一个即继承了Callable接口也继承了Runnable接口的类,这个类就是FutureTask。

2.2 通过ExecutorService去创建

  由于ExecutorService天然支持Callable接口,所以直接submit就可以了。

public class APP {

    public static void main(String[] args) throws Exception {

        class MyCallable implements Callable<Integer> {
            @Override
            public Integer call() throws Exception {
                Thread.sleep(3000);
                System.out.println("end");
                return 200;
            }
        }

        ExecutorService es = Executors.newCachedThreadPool();
        Future<Integer> future = es.submit(new MyCallable());
        System.out.println("when ExecutorService -> " + future.get());

        FutureTask<Integer> task = new FutureTask<Integer>(new MyCallable());
        Thread thread = new Thread(task);
        thread.start();
        System.out.println("when Thread ->" + task.get());
    }
}

备注:

Future的get方法是线程阻塞的,直到Callable的call()方法返回值为止。

再次提醒创建线程不要直接调用run方法。

如果发现理解不了,最好点进去看看源码。

时间: 2024-10-10 09:58:19

Java再学习——线程之创建的相关文章

java 加入一个线程、创建有响应的用户界面 。 示例代码

javajava 加入一个线程.创建有响应的用户界面 . 示例代码 来自thinking in java 4 21章  部分代码  目录21.2.11 thinking in java 4免费下载:http://download.csdn.net/detail/liangrui1988/7580155 package org.rui.thread.concurrent; /** * 加入一个线程 * 一个线程可以在其他线程之上调用join()方法,其效果是等待一段时间直到第二个线程结束才继续执行

java并发学习--线程池(一)

关于java中的线程池,我一开始觉得就是为了避免频繁的创建和销毁线程吧,先创建一定量的线程,然后再进行复用.但是要具体说一下如何做到的,自己又说不出一个一二三来了,这大概就是自己的学习习惯流于表面,不经常深入的结果吧.所以这里决定系统的学习一下线程池的相关知识. 自己稍微总结了一下,学习一些新的知识或者技术的时候,大概都可以分为这么几个点: 1.为什么会有这项技术,用原来的方法有什么问题. 2.这项新技术具体是怎么解决这个问题的(这时可能就要涉及到一些具体的知识点和编码了) 3.是不是使用这项技

java并发之线程的创建(一)

概论 最近在学习并发,于是我在网上搜了一本<java并发编程实战>书学习. 传统创建线程的方式(jdk 1.5之前的方式) 在我印象中创建线程有两种方式 1. 继承Thread类,重写run方法,实例化自己写Thread子类,并用start()方法开启. 2.实现Runnable接口,重写run方法,把Runnable的子类的实例对象作为Thread的构造参数传递进去,创建线程,并开启. 但是我看别人代码时大部分都用第一种方式,直接new Thread 然后重写run方法.其实第二种方式更加符

Java多线程之线程的创建

好久没有更博客了,最近一直在忙工作的事情.现在终于空下来了,这2天会抓紧时间整理多线程和socket,把JavaSE结束掉. 关于多线程,首先会涉及到哪些东西呢?首先要了解线程,为什么要使用线程,线程有什么优势,线程和进程有什么区别呢?了解过大致的线程内容后,就应该编码来实现Java的多线程了.首先2种方式来创建线程类,然后调用对应的API来控制线程.然后还剩下一个最大的也是最重要的一块知识,就是线程同步.前面那些了解线程的生命周期就可以,实际编码中并不会多次写到那些编码,但是线程的同步经常要用

Java基础学习 —— 线程

线程: 多线程的好处:解决了在一个进程中同时执行多个任务代码的问题. 自定义线程的创建方式: 1.自定一个类继承thread类,重写thread的run方法 吧自定义线程的任务代码写在run方法内,创建thread子类的对象并且调用start()方法启动线程. 2.自定义一个类实现runnable接口,实现runnable接口中run方法,吧自定义线程的任务代码写在run方法内部,创建runnable实现类的对象 ,创建thread对象并且把runnable实现类的对象作为参数传递,调用thre

Java再学习——停止一个正在运行的线程

关于这个问题,先了解一下Thread类方法中被废弃的那些方法.suspend(), resume(),stop()/stop(Throwable obj),destroy() 首先,stop(Throwable obj)和destroy()方法在最新的Java中直接就不支持了,没必要去看了.我们只需瞧瞧suspend(), resume(), stop()这三个就行了; suspend()——让当前线程暂停执行 resume()——让当前线程恢复执行 当调用suspend()的时候,线程并没有释

Java再学习——随机面试题

1.final, finally, finalize的区别 final—是修饰符,可以修饰变量.方法和类. final类不能再派生出新的子类即不可当父类: final变量必须在声明时给定初值或在构造方法中赋值,在以后的引用中只能读取,不可修改. final方法不能重载. finally—在异常处理时提供 finally 块来执行收尾操作.如果抛出一个异常,那么相匹配的 catch 子句就会执行,而finally则是只要try代码块有执行(无论return与否),最后都会进入到 finally 块

java io学习 线程池

Java提供的原生线程池技术处理原理很清晰,故只要使用自己的原生线程池技术一般都能满足项目的需求.java提供了很好的线程池实现,比我们自己的实现要更加健壮以及高效,同时功能也更加强大,不建议自己编写.另外有同学可能用过spring的线程池,那么spring线程池和jdk原生线程池有啥区别吗?我们查看源码和官方api可以知道SpringFrameWork 的 ThreadPoolTaskExecutor 是辅助 JDK 的 ThreadPoolExecutor 的工具类,它将属性通过 JavaB

Java再学习——CopyOnWrite容器

一,定义 CopyOnWrite容器即写时复制的容器.通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器.这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素.所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器.目前Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们