zoukankan      html  css  js  c++  java
  • java创建线程的方法

    1.1      创建线程

    1.1.1     无返回值的线程创建

    package com.first;

    public class ThreadTest

    {

        public static void main(String[] args)  {

            System.out.println("主线程ID:"+Thread.currentThread().getId());

            MyThread thread1 = new MyThread("thread1");//1)继承thread类,启动线程

            thread1.start();

            MyThread thread2 = new MyThread("thread2");//2)继承thread类,直接调用方法

            thread2.run();

     

            MyRunnable runnable = new MyRunnable();//3)实现Runnable方法,作为入参

            Thread thread3= new Thread(runnable);

            thread3.start();

     

            Thread thread4 = new MyThread(runnable);//4)继承类也实现接口,实际上用的还是类中的run方法;thread run

            thread4.start();

     

     

        }

    }

    class MyThread extends Thread//1)继承thread类,重写run方法

    {

        private String name;

        public MyThread(String name){

            this.name = name;

        }

        public MyThread(Runnable runnable){//4Runnable入参传入

                   super(runnable);

               }

     

        @Override

        public void run()

        {

            System.out.println(" thread run name:"+name+" 子线程ID:"+Thread.currentThread().getId());

        }

    }

    class MyRunnable implements Runnable{//3)实现runable方法

     

        public MyRunnable()

        {

        }

        @Override

        public void run() {

            System.out.println("MyRunnable 子线程ID"+Thread.currentThread().getId());

        }

    }

    运行结果

    主线程ID:1

     thread run name:thread2 子线程ID:1

     thread run name:thread1 子线程ID:11

    MyRunnable 子线程ID13

     thread run name:null 子线程ID:14

     

    线程Thread实际上是实现了Runable接口,class Thread implements Runnable{},并且定义了一个引用private Runnable target;用于保存构造函数传入的继承类引用MyRunnable的入参,public Thread(Runnable target) {init(null, target, "Thread-" + nextThreadNum(), 0);} Thread重写了Runable接口的run函数

    public void run() {

            if (target != null) {

                target.run();

            }

    }

    所以如果是情况(1)子类继承Thread类,重写run()方法,则targetnullThread类的run方法实现也没有用,因为被子类重写了。调用的是子类实现的方法;如果是情况(2),没有启动线程而是直接调用子类的run方法,则跟调用一般方法一样,只不过是主线程在调用方法,thread2被创建,但是没有被启动;如果像情况(3)因为传入了MyRunable对象的引用,所以target不在为空,而且没有子类重写Threadrun()方法,所以会直接调用Thread默认的run()方法,target不为空,所以执行的是传入的MyRunable的方法;如果是情况(4)即传入了MyRunable的方法,子类也继承实现了run()方法,则按照顺序,MyRunable作为入参传入,MyThread子类调用了supuer的构造函数,传给父类的target。因为MyThread子类,重写父类的run方法,所以,无论是否传入target参数,Thread类的run()方法实现都会被MyThread子类的run()方法重写。所以最后执行的是MyThread子类中实现的run方法。

    总结下创建线程的方法主要有两种:(1)继承Thread类,重写该类的run()方法.(2)实现Runnable接口,实现接口的run方法,作为Thread构造函数的入参传入任务。Thread的start方法来创建一个新线程来执行该子任务。如果调用Runnable的run方法的话,是不会创建新线程的,这跟普通的方法调用没有任何区别。

    这2种方式都可以用来创建线程去执行子任务,具体选择哪一种方式要看自己的需求。直接继承Thread类的话,可能比实现Runnable接口看起来更加简洁,但是由于Java只允许单继承,所以如果自定义类需要继承其他类,则只能选择实现Runnable接口。

    1.1.2     有返回值的线程创建

    上述两种方法,在执行完任务之后无法获取执行结果。如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。所以需要有返回值的线程实现。基于FutureTask类,Callable接口,Runnable, Future接口实现带返回值的线程。Runnable 接口是提供run方法,FutureTask实现接口的run方法,作为线程的执行方法。Future接口则是提供了几个函数,用来操作线程的执行,获取线程返回值。FutureTask实现了RunnableFuture接口,RunnableFuture继承了Runnable, Future接口。Callable接口只有一个带返回值的call函数,需要继承实现Callablecall函数,call函数是线程真正要执行的内容,在FutureTask中实现的run方法中会调用call函数来执行线程的任务内容。

    1FutureTask实现了RunnableFuture接口

    public class FutureTask<V> implements RunnableFuture<V>

    2RunnableFuture继承了Runnable, Future接口

    public interface RunnableFuture<V> extends Runnable, Future<V>

    {

        void run();

    }

    3FutureTask构造函数

    public FutureTask(Callable<V> callable) {

            if (callable == null)

                throw new NullPointerException();

            this.callable = callable;// FutureTask定义callable引用指向Callable对象

            this.state = NEW;       // ensure visibility of callable

    }

    4Callable的定义

    public interface Callable<V> {

        V call() throws Exception;//只有一个call函数,线程执行任务

    }

    5FutureTaskrun函数的实现

      public void run() {//实现Runable接口的run函数

            if (state != NEW ||

                !UNSAFE.compareAndSwapObject(this, runnerOffset,

                                             null, Thread.currentThread()))

                return;

            try {

                Callable<V> c = callable;//赋值引用

                if (c != null && state == NEW) {

                    V result;

                    boolean ran;

                    try {

                        result = c.call();//调用了callablecall函数

                        ran = true;

                    } catch (Throwable ex) {

                        result = null;

                        ran = false;

                        setException(ex);

                    }

                    if (ran)

                        set(result);//将执行结果赋值给outcome引用

                }

            } finally {

                // runner must be non-null until state is settled to

                // prevent concurrent calls to run()

                runner = null;

                // state must be re-read after nulling runner to prevent

                // leaked interrupts

                int s = state;

                if (s >= INTERRUPTING)

                    handlePossibleCancellationInterrupt(s);

            }

    }

    6FutureTask中的set函数

    protected void set(V v) {

            if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {

                outcome = v;//执行结果赋值给outcome

                UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state

                finishCompletion();

            }

        }

    7FutureTaskget()函数

    public V get() throws InterruptedException, ExecutionException {

            int s = state;

            if (s <= COMPLETING)

                s = awaitDone(false, 0L);//等待线程执行完毕

            return report(s);

        }

    8FutureTaskreport函数返回执行结果

    private V report(int s) throws ExecutionException {

            Object x = outcome;//返回线程的执行结果

            if (s == NORMAL)

                return (V)x;//返回执行结果

            if (s >= CANCELLED)

                throw new CancellationException();

            throw new ExecutionException((Throwable)x);

        }

    9Future接口的方法定义

    public interface Future<V> {

        boolean cancel(boolean mayInterruptIfRunning);

        boolean isCancelled();

        boolean isDone();

        V get() throws InterruptedException, ExecutionException;//线程操作方法

        V get(long timeout, TimeUnit unit)

            throws InterruptedException, ExecutionException, TimeoutException;

    }

    综上所述,FutureTask实现Runable接口,是为了实现线程执行函数run方法。FutureTask实现future接口,是为了实现Future操作线程的方法,例如V get()返回执行结果。FutureTaskCallable为入参,是要执行Callable中的线程任务call()方法。FutureTaskrun()方法中会调用Callablecall()方法。

    所以给出实际的例子

    package com.first;

    import java.util.concurrent.Callable;

    import java.util.concurrent.FutureTask;

    public class ThreadTest

    {

        public static void main(String[] args)  {

         

            // 使用FutureTask来包装Callable对象

            ThreadByCallable rt = new ThreadByCallable();//创建任务对象

            FutureTask<Integer> task = new FutureTask<Integer>(rt);//5)使用

           // task继承了Runable接口,所以可以作为Thread入参

                 new Thread(task, "有返回值的线程").start();

            try {

                // 获取线程返回值

                System.out.println("thread5:返回值:" + task.get());

            } catch (Exception ex) {

                ex.printStackTrace();

            }

        }

    }

    class ThreadByCallable implements Callable<Integer> {//创建类实现Callable接口

     

        @Override

        public Integer call() {

            System.out.println("thread5call" + Thread.currentThread().getName());

            // call()方法有返回值

            return 5;

        }

     

    }

    自己编了一个股票监控软件,有如下功能,有兴趣的朋友可以下载;

    (1)   个股监测。监测个股实时变化,可以监测个股大单交易、急速拉升和下降、主力入场和出场、股票最高点和最低点提醒。检测到最高点、最低点、主力进场点、主力退场点、急速拉升点、急速下跌点,给出语音或者声音提醒,不用再时刻看着大盘了,给你更多自由的时间;

    (2)   大盘监测。监测大盘的走势,采用上证、深证、创业三大指数的综合指数作为大盘走势。并实时监测大盘的最高点和最低点、中间的转折点。

    (3)   股票推荐。还能根据历史数据长期或短期走势进行分析,对股市3千多个股票进行分析对比,选出涨势良好的股票,按照增长速度从大到小排序,推荐给你涨势良好的股票;

    下载地址:

    1.0.3版本(修复大盘指数崩溃缺陷)下载地址:

    链接:https://pan.baidu.com/s/1BJcTp-kdniM7VE9K5Kd3vg 提取码:003h

    更新链接:

    https://www.cnblogs.com/bclshuai/p/10621613.html

  • 相关阅读:
    Zabbix二次开发_03api列表
    Zabbix二次开发_02获取数据
    Zabbix二次开发_01基础
    运维监控体系
    并发检测主机ip存活脚本
    Python的paramiko模块ssh操作
    Oracle数据迁移expdp/impdp
    Mongodb的备份与恢复
    利用微信小程序实现web监控界面
    不会JS中的OOP,你也太菜了吧!(第二篇)
  • 原文地址:https://www.cnblogs.com/bclshuai/p/10245149.html
Copyright © 2011-2022 走看看