• java基础---->多线程之Runnable(一)


      java线程的创建有两种方式,这里我们通过简单的实例来学习一下。一切都明明白白,但我们仍匆匆错过,因为你相信命运,因为我怀疑生活。

    java中多线程的创建

    一、通过继承Thread类来创建多线程

    public class HelloThread extends Thread {
        @Override
        public void run() {
            try {
                TimeUnit.SECONDS.sleep(1);
                System.out.println("Hello from a thread!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            HelloThread helloThread = new HelloThread();
            helloThread.start();
            System.out.println("In main thread.");
        }
    }

    运行的结果如下:

    In main thread.
    Hello from a thread!

    我们这里对Thread类的start的方法做一些说明,官方文档的说明:

    Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread. 
    The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method). 
    It is never legal(合法) to start a thread more than once(不止一次). In particular, a thread may not be restarted once it has completed execution. 
    
    Throws: 
        IllegalThreadStateException - if the thread was already started

    我们在上述例子的基础上,对上述的说明做一个代码的测试。在helloThread.start();代码的后面添加代码:

    System.out.println(helloThread.getName());
    helloThread.start();

    一次的运行结果如下所示,在添加代码的第二行(helloThread.start();)报的错误。

    Exception in thread "main" java.lang.IllegalThreadStateException
    Thread-0
        at java.lang.Thread.start(Thread.java:708)
        at com.linux.huhx.thread.HelloThread.main(HelloThread.java:22)
    Hello from a thread!

    如果在添加helloThread.start();之前让主线程睡眠3秒,也就是让先启动的helloThread线程执行完毕。我们再调用helloThread.start()启动线程。

    TimeUnit.SECONDS.sleep(3);
    System.out.println(helloThread.getName());
    helloThread.start();

    运行的结果如下:

    Hello from a thread!
    Thread-0
    Exception in thread "main" java.lang.IllegalThreadStateException
        at java.lang.Thread.start(Thread.java:708)
        at com.linux.huhx.thread.HelloThread.main(HelloThread.java:22)

    二、通过实现Runnable接口来创建多线程

    public class HelloRunnable implements Runnable {
    
        @Override
        public void run() {
            try {
                System.out.println("Hello from a thread!");
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            Thread thread = new Thread(new HelloRunnable());
            thread.start();
            System.out.println("In main method.");
        }
    }

    运行的结果如下:

    In main method.
    Hello from a thread!

      这种使用实现HelloRunnable接口的方式是比较推崇的,因为java类中只能单继承可以多实现。现在看一下它的简单原理new Thread(new HelloRunnable())的源码如下:

    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

    init的方法是初始化线程的一些信息:

    private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }
    
        this.name = name;
    
        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            if (security != null) {
                g = security.getThreadGroup();
            }
    
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }
    
        g.checkAccess();
    
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }
    
        g.addUnstarted();
    
        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext = acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        this.stackSize = stackSize;
        tid = nextThreadID();
    }

      最重要的一行代码就是this.target = target;设置了线程target为我们的Runnable对象。我们都知道thread.start()启动一个线程,实际是调用线程的run方法。现在我们看一下Thread类的run方法。

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

      可以看到是调用了target的run方法,在我们这里就是(HelloRunnable)。对于继承Thread的的情况来说,就拿上述的HelloThread来讲,它里面的target是空的。不过执行的run方法是HelloThread重写的run方法。所以不存在HelloThread中没有target就不会执行的情况。

    友情链接

  • 相关阅读:
    posix多线程有感线程高级编程(线程属性函数总结)
    posix多线程有感线程高级编程(线程属性pthread_attr_t)
    posix多线程有感线程高级编程(条件变量属性)
    posix多线程有感线程高级编程(线程属性pthread_attr_t)实时调度
    posix多线程有感自旋锁
    posix多线程有感线程高级编程(线程属性函数总结)(代码)
    寒假Day58:javaTreeSetComparator
    Day62:java多线程
    寒假Day58:蓝桥杯2n皇后问题八皇后变形
    寒假Day57:CodeForces1325C Ehab and Pathetic MEXs树统计度思维
  • 原文地址:https://www.cnblogs.com/huhx/p/baseusejavathreadrunnable.html
Copyright © 2020-2023  润新知