精华内容
下载资源
问答
  • java中Thread用法

    万次阅读 2015-05-13 10:02:11
    上下文切换三.Thread的方法线程的状态 在正式学习Thread的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread的方法的理解。 线程从创建到最终的消亡,要经历若干个状态。...

    一.线程的状态

    二.上下文切换

    三.Thread类中的方法

    线程的状态

     在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread类中的方法的理解。

      线程从创建到最终的消亡,要经历若干个状态。一般来说,线程包括以下这几个状态:创建(new)、就绪(runnable)、运行(running)、阻塞(blocked)、time waiting、waiting、消亡(dead)。

      当需要新起一个线程来执行某个子任务时,就创建了一个线程。但是线程创建之后,不会立即进入就绪状态,因为线程的运行需要一些条件(比如内存资源,在前面的JVM内存区域划分一篇博文中知道程序计数器、Java栈、本地方法栈都是线程私有的,所以需要为线程分配一定的内存空间),只有线程运行需要的所有条件满足了,才进入就绪状态。

      当线程进入就绪状态后,不代表立刻就能获取CPU执行时间,也许此时CPU正在执行其他的事情,因此它要等待。当得到CPU执行时间之后,线程便真正进入运行状态。

      线程在运行状态过程中,可能有多个原因导致当前线程不继续运行下去,比如用户主动让线程睡眠(睡眠一定的时间之后再重新执行)、用户主动让线程等待,或者被同步块给阻塞,此时就对应着多个状态:time waiting(睡眠或等待一定的事件)、waiting(等待被唤醒)、blocked(阻塞)。

      当由于突然中断或者子任务执行完毕,线程就会被消亡。

      下面这副图描述了线程从创建到消亡之间的状态:

    这里写图片描述

     在有些教程上将blocked、waiting、time waiting统称为阻塞状态,这个也是可以的,只不过这里我想将线程的状态和Java中的方法调用联系起来,所以将waiting和time waiting两个状态分离出来。

    上下文切换

    对于单核CPU来说(对于多核CPU,此处就理解为一个核),CPU在一个时刻只能运行一个线程,当在运行一个线程的过程中转去运行另外一个线程,这个叫做线程上下文切换(对于进程也是类似)。

      由于可能当前线程的任务并没有执行完毕,所以在切换时需要保存线程的运行状态,以便下次重新切换回来时能够继续切换之前的状态运行。举个简单的例子:比如一个线程A正在读取一个文件的内容,正读到文件的一半,此时需要暂停线程A,转去执行线程B,当再次切换回来执行线程A的时候,我们不希望线程A又从文件的开头来读取。

      因此需要记录线程A的运行状态,那么会记录哪些数据呢?因为下次恢复时需要知道在这之前当前线程已经执行到哪条指令了,所以需要记录程序计数器的值,另外比如说线程正在进行某个计算的时候被挂起了,那么下次继续执行的时候需要知道之前挂起时变量的值时多少,因此需要记录CPU寄存器的状态。所以一般来说,线程上下文切换过程中会记录程序计数器、CPU寄存器状态等数据。

      说简单点的:对于线程的上下文切换实际上就是 存储和恢复CPU状态的过程,它使得线程执行能够从中断点恢复执行。

      虽然多线程可以使得任务执行的效率得到提升,但是由于在线程切换时同样会带来一定的开销代价,并且多个线程会导致系统资源占用的增加,所以在进行多线程编程时要注意这些因素。

    Thread类中的方法

    通过查看java.lang.Thread类的源码可知:

    public class Thread implements Runnable {
        private static final int NANOS_PER_MILLI = 1000000;
    
        /** Park states */
        private static class ParkState {
            /** park state indicating unparked */
            private static final int UNPARKED = 1;
    
            /** park state indicating preemptively unparked */
            private static final int PREEMPTIVELY_UNPARKED = 2;
    
            /** park state indicating parked */
            private static final int PARKED = 3;
        }
    
        /**
         * A representation of a thread's state. A given thread may only be in one
         * state at a time.
         */
        public enum State {
            /**
             * The thread has been created, but has never been started.
             */
            NEW,
            /**
             * The thread may be run.
             */
            RUNNABLE,
            /**
             * The thread is blocked and waiting for a lock.
             */
            BLOCKED,
            /**
             * The thread is waiting.
             */
            WAITING,
            /**
             * The thread is waiting for a specified amount of time.
             */
            TIMED_WAITING,
            /**
             * The thread has been terminated.
             */
            TERMINATED
        }
    
        /**
         * The maximum priority value allowed for a thread.
         * This corresponds to (but does not have the same value as)
         * {@code android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY}.
         */
        public static final int MAX_PRIORITY = 10;
    
        /**
         * The minimum priority value allowed for a thread.
         * This corresponds to (but does not have the same value as)
         * {@code android.os.Process.THREAD_PRIORITY_LOWEST}.
         */
        public static final int MIN_PRIORITY = 1;
    
        /**
         * The normal (default) priority value assigned to the main thread.
         * This corresponds to (but does not have the same value as)
         * {@code android.os.Process.THREAD_PRIORITY_DEFAULT}.
    
         */
        public static final int NORM_PRIORITY = 5;
    
        /* Some of these are accessed directly by the VM; do not rename them. */
        private volatile long nativePeer;
        volatile ThreadGroup group;
        volatile boolean daemon;
        volatile String name;
        volatile int priority;
        volatile long stackSize;
        Runnable target;
        private static int count = 0;
    

    Thread类实现了Runnable接口,在Thread类中,有一些比较关键的属性,比如name是表示Thread的名字,可以通过Thread类的构造器中的参数来指定线程名字,priority表示线程的优先级(最大值为10,最小值为1,默认值为5),daemon表示线程是否是守护线程,target表示要执行的任务。

      下面是Thread类中常用的方法:

      以下是关系到线程运行状态的几个方法:

      1)start方法

      start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源。

      2)run方法

      run()方法是不需要用户来调用的,当通过start方法启动一个线程之后,当线程获得了CPU执行时间,便进入run方法体去执行具体的任务。注意,继承Thread类必须重写run方法,在run方法中定义具体要执行的任务。

      3)sleep方法

      sleep方法有两个重载版本:

    sleep(long millis)     //参数为毫秒
    
    sleep(long millis,int nanoseconds)    //第一参数为毫秒,第二个参数为纳秒

    sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务。

      但是有一点要非常注意,sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象。看下面这个例子就清楚了:

    public class Test {
    
        private int i = 10;
        private Object object = new Object();
    
        public static void main(String[] args) throws IOException  {
            Test test = new Test();
            MyThread thread1 = test.new MyThread();
            MyThread thread2 = test.new MyThread();
            thread1.start();
            thread2.start();
        } 
    
    
        class MyThread extends Thread{
            @Override
            public void run() {
                synchronized (object) {
                    i++;
                    System.out.println("i:"+i);
                    try {
                        System.out.println("线程"+Thread.currentThread().getName()+"进入睡眠状态");
                        Thread.currentThread().sleep(10000);
                    } catch (InterruptedException e) {
                        // TODO: handle exception
                    }
                    System.out.println("线程"+Thread.currentThread().getName()+"睡眠结束");
                    i++;
                    System.out.println("i:"+i);
                }
            }
        }
    }

    输出结果:

    这里写图片描述

    从上面输出结果可以看出,当Thread-0进入睡眠状态之后,Thread-1并没有去执行具体的任务。只有当Thread-0执行完之后,此时Thread-0释放了对象锁,Thread-1才开始执行。

      注意,如果调用了sleep方法,必须捕获InterruptedException异常或者将该异常向上层抛出。当线程睡眠时间满后,不一定会立即得到执行,因为此时可能CPU正在执行其他的任务。所以说调用sleep方法相当于让线程进入阻塞状态。

      4)yield方法

      调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。它跟sleep方法类似,同样不会释放锁。但是yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。

      注意,调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。

      5)join方法

      join方法有三个重载版本:

    join()
    join(long millis)     //参数为毫秒
    join(long millis,int nanoseconds)    //第一参数为毫秒,第二个参数为纳秒

    假如在main线程中,调用thread.join方法,则main方法会等待thread线程执行完毕或者等待一定的时间。如果调用的是无参join方法,则等待thread执行完毕,如果调用的是指定了时间参数的join方法,则等待一定的时间。

      看下面一个例子:

    public class Test {
    
        public static void main(String[] args) throws IOException  {
            System.out.println("进入线程"+Thread.currentThread().getName());
            Test test = new Test();
            MyThread thread1 = test.new MyThread();
            thread1.start();
            try {
                System.out.println("线程"+Thread.currentThread().getName()+"等待");
                thread1.join();
                System.out.println("线程"+Thread.currentThread().getName()+"继续执行");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } 
    
        class MyThread extends Thread{
            @Override
            public void run() {
                System.out.println("进入线程"+Thread.currentThread().getName());
                try {
                    Thread.currentThread().sleep(5000);
                } catch (InterruptedException e) {
                    // TODO: handle exception
                }
                System.out.println("线程"+Thread.currentThread().getName()+"执行完毕");
            }
        }
    }

     输出结果:

    这里写图片描述

    可以看出,当调用thread1.join()方法后,main线程会进入等待,然后等待thread1执行完之后再继续执行。

      实际上调用join方法是调用了Object的wait方法,这个可以通过查看源码得知:

     public final void join() throws InterruptedException {
            synchronized (lock) {
                while (isAlive()) {
                    lock.wait();
                }
            }
        }
    
    
    
    
     public final void join(long millis, int nanos) throws InterruptedException {
            if (millis < 0 || nanos < 0 || nanos >= NANOS_PER_MILLI) {
                throw new IllegalArgumentException("bad timeout: millis=" + millis + ",nanos=" + nanos);
            }
    
            // avoid overflow: if total > 292,277 years, just wait forever
            boolean overflow = millis >= (Long.MAX_VALUE - nanos) / NANOS_PER_MILLI;
            boolean forever = (millis | nanos) == 0;
            if (forever | overflow) {
                join();
                return;
            }
    
            synchronized (lock) {
                if (!isAlive()) {
                    return;
                }
    
                // guaranteed not to overflow
                long nanosToWait = millis * NANOS_PER_MILLI + nanos;
    
                // wait until this thread completes or the timeout has elapsed
                long start = System.nanoTime();
                while (true) {
                    lock.wait(millis, nanos);
                    if (!isAlive()) {
                        break;
                    }
                    long nanosElapsed = System.nanoTime() - start;
                    long nanosRemaining = nanosToWait - nanosElapsed;
                    if (nanosRemaining <= 0) {
                        break;
                    }
                    millis = nanosRemaining / NANOS_PER_MILLI;
                    nanos = (int) (nanosRemaining - millis * NANOS_PER_MILLI);
                }
            }
        }
    

    wait方法会让线程进入阻塞状态,并且会释放线程占有的锁,并交出CPU执行权限。

      由于wait方法会让线程释放对象锁,所以join方法同样会让线程释放对一个对象持有的锁。具体的wait方法使用在后面文章中给出。

     6)interrupt方法

      interrupt,顾名思义,即中断的意思。单独调用interrupt方法可以使得处于阻塞状态的线程抛出一个异常,也就说,它可以用来中断一个正处于阻塞状态的线程;另外,通过interrupt方法和isInterrupted()方法来停止正在运行的线程。

      下面看一个例子:

    public class Test {
    
        public static void main(String[] args) throws IOException  {
            Test test = new Test();
            MyThread thread = test.new MyThread();
            thread.start();
            try {
                Thread.currentThread().sleep(2000);
            } catch (InterruptedException e) {
    
            }
            thread.interrupt();
        } 
    
        class MyThread extends Thread{
            @Override
            public void run() {
                try {
                    System.out.println("进入睡眠状态");
                    Thread.currentThread().sleep(10000);
                    System.out.println("睡眠完毕");
                } catch (InterruptedException e) {
                    System.out.println("得到中断异常");
                }
                System.out.println("run方法执行完毕");
            }
        }
    }

    输出结果:

    这里写图片描述

    从这里可以看出,通过interrupt方法可以中断处于阻塞状态的线程。那么能不能中断处于非阻塞状态的线程呢?看下面这个例子:

    public class Test {
    
        public static void main(String[] args) throws IOException  {
            Test test = new Test();
            MyThread thread = test.new MyThread();
            thread.start();
            try {
                Thread.currentThread().sleep(2000);
            } catch (InterruptedException e) {
    
            }
            thread.interrupt();
        } 
    
        class MyThread extends Thread{
            @Override
            public void run() {
                int i = 0;
                while(i<Integer.MAX_VALUE){
                    System.out.println(i+" while循环");
                    i++;
                }
            }
        }
    }

    运行该程序会发现,while循环会一直运行直到变量i的值超出Integer.MAX_VALUE。所以说直接调用interrupt方法不能中断正在运行中的线程。

      但是如果配合isInterrupted()能够中断正在运行的线程,因为调用interrupt方法相当于将中断标志位置为true,那么可以通过调用isInterrupted()判断中断标志是否被置位来中断线程的执行。比如下面这段代码:

    public class Test {
    
        public static void main(String[] args) throws IOException  {
            Test test = new Test();
            MyThread thread = test.new MyThread();
            thread.start();
            try {
                Thread.currentThread().sleep(2000);
            } catch (InterruptedException e) {
    
            }
            thread.interrupt();
        } 
    
        class MyThread extends Thread{
            @Override
            public void run() {
                int i = 0;
                while(!isInterrupted() && i<Integer.MAX_VALUE){
                    System.out.println(i+" while循环");
                    i++;
                }
            }
        }
    }

    运行会发现,打印若干个值之后,while循环就停止打印了。

      但是一般情况下不建议通过这种方式来中断线程,一般会在MyThread类中增加一个属性 isStop来标志是否结束while循环,然后再在while循环中判断isStop的值。

    class MyThread extends Thread{
            private volatile boolean isStop = false;
            @Override
            public void run() {
                int i = 0;
                while(!isStop){
                    i++;
                }
            }
    
            public void setStop(boolean stop){
                this.isStop = stop;
            }
        }

    那么就可以在外面通过调用setStop方法来终止while循环。

      7)stop方法

      stop方法已经是一个废弃的方法,它是一个不安全的方法。因为调用stop方法会直接终止run方法的调用,并且会抛出一个ThreadDeath错误,如果线程持有某个对象锁的话,会完全释放锁,导致对象状态不一致。所以stop方法基本是不会被用到的。

      8)destroy方法

      destroy方法也是废弃的方法。基本不会被使用到。

      以下是关系到线程属性的几个方法:

      1)getId

      用来得到线程ID

      2)getName和setName

      用来得到或者设置线程名称。

      3)getPriority和setPriority

      用来获取和设置线程优先级。

      4)setDaemon和isDaemon

      用来设置线程是否成为守护线程和判断线程是否是守护线程。

      守护线程和用户线程的区别在于:守护线程依赖于创建它的线程,而用户线程则不依赖。举个简单的例子:如果在main线程中创建了一个守护线程,当main方法运行完毕之后,守护线程也会随着消亡。而用户线程则不会,用户线程会一直运行直到其运行完毕。在JVM中,像垃圾收集器线程就是守护线程。

      Thread类有一个比较常用的静态方法currentThread()用来获取当前线程。

      在上面已经说到了Thread类中的大部分方法,那么Thread类中的方法调用到底会引起线程状态发生怎样的变化呢?下面一幅图就是在上面的图上进行改进而来的:

    这里写图片描述

    原文链接

    展开全文
  • public class MyThread extends Thread { private String msg; public MyThread(String s) { msg = s; } public void run() { System.out.println(msg); } } public static void main(String[] args) { ...
  • java中Thread类的join方法

    千次阅读 2017-11-13 13:21:03
    那么我们如何实现让线程T1,T2,T3,在T1执行完成后才执行T2,T2执行完成后才执行T3,也就是线程的串行化,通过Thread类的join方法就可以实现。 join方法:将该线程加入当前线程,当前线程等待加入线程执行完成...
    单核cpu运行多线程时底层实现原理是多个线程间切换,由于cpu的处理速度很快,看上去像多个线程同时运行。那么我们如何实现让线程T1,T2,T3,在T1执行完成后才执行T2,T2执行完成后才执行T3,也就是线程的串行化,通过Thread类的join方法就可以实现。

    join方法:将该线程加入当前线程,当前线程等待加入线程执行完成才继续执行。
    例子:
    public class ThreadJoinTest implements Runnable {
    public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new ThreadJoinTest());
    thread.start();
    thread.join();
    System.out.println("主线程结束");
    }

    @Override
    public void run() {
    System.out.println("子线程开始");
    for(int i = 0; i < 5; i++) {
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(i);
    }
    System.out.println("子线程结束");
    }
    }
    执行结果:
    join(long  millis)方法:将该线程加班当前线程,当前线程等待加入线程millis时间,当达到millis时间后不管加入线程是否完成,当前线程都继续执行,若加入线程在小于millis时间执行完成,则当前线程等待时间等于加入线程的执行时间。
    例子:
    public class ThreadJoinTest implements Runnable {
    public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new ThreadJoinTest());
    thread.start();
    thread.join(2000);
    System.out.println("主线程结束");
    }

    @Override
    public void run() {
    System.out.println("子线程开始");
    for(int i = 0; i < 5; i++) {
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(i);
    }
    System.out.println("子线程结束");
    }
    }
    执行结果:

    展开全文
  • Java中Thread类的方法简介

    万次阅读 2018-06-05 17:37:48
    Thread t1 = new Thread(); t1.start(); 新建线程,应该调用start()方法启动线程;如果直接调用run()方法,该方法也会执行,但会被当做一个普通的方法,在当前线程顺序执行;而如果使用start()方法,则会创建一个...

    1.新建线程

    Thread t1 = new Thread();
    t1.start();

    新建线程,应该调用start()方法启动线程;如果直接调用run()方法,该方法也会执行,但会被当做一个普通的方法,在当前线程中顺序执行;而如果使用start()方法,则会创建一个新的线程执行run()方法。

    2.线程中断

    public void interrupt();
    public boolean isInterrupted();
    public static boolean interrupted();

    三个方法很相似,线程中断只是通知目标线程有人希望你退出,而并不是使目标线程退出。
    第一个方法是通知目标线程中断,即设置目标线称的中断标志位;
    第二个方法判断当前线程是否被中断,如果被中断(即中断标志位被设置),则返回true,否则返回false;
    第三个方法判断当前线程的中断状态,并清除该线程的中断标志位(也就意味着,如果连续调用两次该方法,并且中间没有再次设置中断标志位,第二次会返回false,因为中断标志位已经被清除)。

    public static native void sleep(long millis) throws InterruptedException;

    sleep()方法会将当前线程休眠若干ms,如果在休眠期间被调用interrupt()方法,则会抛出InterruptedException异常。如下:

    public class TestThread implements Runnable{
        @Override
        public void run() {
            while(true) {
                if(Thread.currentThread().isInterrupted()){ //如果当前线程已经被设置了中断标志位,则返回true
                    System.out.println("Interrupted");
                    break;
                }
    
                try {
                    Thread.currentThread().sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("Interruted when sleep!");
                    Thread.currentThread().interrupt(); //Thread.sleep()方法由于中断而抛出异常,此时,它会清除中断标记;
                }
    
                Thread.yield();
            }
        }
    
        public static void main(String[] args){
            Thread t1 = new Thread(new TestThread());
            t1.start();
    
            t1.interrupt(); //设置目标线程的中断标志位,中断标志位表示当前线程已经被中断了
        }
    }

    3.等待(wait)和通知(notify)

    public final void wait() throws InterruptedException;
    public final native void notify();
    public final native void notifyAll();

    obj.wait()是设置当前线程在该对象上等待,直到有线程调用obj.notify()方法(或notifyAll()方法)。当调用wait()方法后,该线程会进入一个等待队列,等待队列中可能有多个线程,notify()会随机唤醒其中一个线程,而notifyAll()会唤醒所有线程。
    wait()和notify()方法必须在sychronized代码块中,调用这些方法时都需要先获得目标对象的一个监视器,然后调用这些方法时会释放监视器
    与sleep不同的是,sleep()会一直占有所持有的锁,而wait()会释放锁。

    4.等待线程(join)和谦让(yield)

    public final void join() throws InterruptedException;
    public static native void yield();

    如果一个线程的执行需要另一个线程的参与(比如当前线程执行需要另一个线程执行完毕才能继续执行),这时候可以调用join()方法。t1.join()方法表示等待线程t1执行完毕之后,当前线程再继续执行。当然也可以给join()设置时间参数。
    注:join()的本质是让调用线程wait()在当前线程对象实例上,其部分源码如下:

    while (isAlive()) {
       wait(0);
    }

    当线程执行完毕后,它会让被等待的线程在退出前调用notifyAll()通知所有等待的线程继续执行。因此不要在Thread对象实例上使用类似wait()或者notify()等方法。
    yield()方法是使当前线程让出CPU,但该线程会再次抢夺CPU。

    展开全文
  • java中thread的start()和run()的区别

    万次阅读 2010-08-26 07:06:00
    java中thread的start()和run()的区别: 1.start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码: 通过调用Thread类的start()方法来启动一...

    java中thread的start()和run()的区别:

    1.start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码:

    通过调用Thread类的start()方法来启动一个线程,
    这时此线程是处于就绪状态,
    并没有运行。
    然后通过此Thread类调用方法run()来完成其运行操作的,
    这里方法run()称为线程体,
    它包含了要执行的这个线程的内容,
    Run方法运行结束,
    此线程终止,
    而CPU再运行其它线程,

     

    2.run()方法当作普通方法的方式调用,程序还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码:

    而如果直接用Run方法,
    这只是调用一个方法而已,
    程序中依然只有主线程--这一个线程,
    其程序执行路径还是只有一条,
    这样就没有达到写线程的目的。

     

    举例说明一下:

    记住:线程就是为了更好地利用CPU,
    提高程序运行速率的!

    public class TestThread1{
    public static void main(String[] args){
    Runner1 r=new Runner1();
    //r.run();//这是方法调用,而不是开启一个线程
    Thread t=new Thread(r);//调用了Thread(Runnable target)方法。且父类对象变量指向子类对象。
    t.start();

    for(int i=0;i<100;i++){
    System.out.println("进入Main Thread运行状态");
    System.out.println(i);
    }
    }
    }
    class Runner1 implements Runnable{ //实现了这个接口,jdk就知道这个类是一个线程
    public void run(){

    for(int i=0;i<100;i++){
    System.out.println("进入Runner1运行状态");
    System.out.println(i);
    }
    }
    }

    同时摘取一段外文网站论坛上的解释:
    Why do we need start() method in Thread class? In Java API description for Thread class is written : "Java Virtual Machine calls the run method of this thread..".

    Couldn't we call method run() ourselves, without doing double call: first we call start() method which calls run() method? What is a meaning to do things such complicate?

     

     

    There is some very small but important difference between using start() and run() methods. Look at two examples below:

    Example one:

    Code:

    Thread one = new Thread();
    Thread two = new Thread();
    one.run();
    two.run();

    Example two:

    Code:

    Thread one = new Thread();
    Thread two = new Thread();
    one.start();
    two.start();

    The result of running examples will be different.

    In Example one the threads will run sequentially: first, thread number one runs, when it exits the thread number two starts.

    In Example two both threads start and run simultaneously.

    Conclusion: the start() method call run() method asynchronously (does not wait for any result, just fire up an action), while we run run() method synchronously - we wait when it quits and only then we can run the next line of our code.

     

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/tornado886/archive/2009/09/06/4524346.aspx

     

     

    Thread对象的run()方法在一种循环下,使线程一直运行,直到不满足条件为止,在你的main()里创建并运行了一些线程,调用Thread类的start()方法将为线程执行特殊的初始化的过程,来配置线程,然后由线程执行机制调用run()。如果你不调用start()线程就不会启动。

     

     

    因为线程调度机制的行为是不确定的,所以每次运行该程序都会有不同的结果,你可以把你的循环次数增多些,然后看看执行的结果,你会发现main()的线程和Thread1是交替运行的。
    4.还有就是尽管线程的调度顺序是不固定的,但是如果有很多线程被阻塞等待运行,调度程序将会让优先级高的线程先执行,而优先级低的线程执行的频率会低一些。

     

     

    线程的启动是比较复杂的,需要为线程分配资源,它的START方法被调用时系统才会为线程分配资源。
    你上面调用线程的run方法只能算普通的方法调用一样,得运行完run里面的代码整个程序才能往下进行,而如果调用start方法,线程和MAIN方法就会抢资源,打印的语句会交替出现,你把线程里的循环次数加到300,试一下依次调run、start和两次都调start方法时所出现的情况应该能看出点端倪~~~

    展开全文
  • JAVA中 Thread Dump 的方法

    千次阅读 2011-11-29 12:00:41
    Thread Dump用来诊断Java应用的问题,可以用来查找内存泄露,发现死锁线程等等。通过它可以得到线程,线程运行状态、标识、调用的堆栈,堆栈包含完整的类名,所执行的方法,以及源代码所在的行数等等信息 使用方法...
  • Java中Thread.yield()

    千次阅读 2018-10-05 19:55:56
    Thread.yield( )方法   线程让步。使用了这个方法之后,线程会让出CPU执行权,让自己或者其它的线程运行。也就是说,当前线程调用yield()之后,并不能保证:其它具有相同优先级的线程一定能获得执行权,也有可能...
  • java中Thread类的join()方法

    万次阅读 2012-03-10 11:45:47
    Thread有一个join()方法,在一个线程启动另外一个线程的join方法,当前线程将会挂起,而执行被启动的线程,知道被启动的线程执行完毕后,当前线程才开始执行。 下面我们新建两个继承Thread的类,让其中一个...
  • Java有两种方式实现多线程,第一个是继承Thread类,第二个是实现Runnable接口。他们之间的联系: 1、Thread类实现了Runable接口。 2、都需要重写里面Run方法。 他们之间的区别“ 1、实现Runnable的类更具有健壮性,...
  • Java的sleep函数
  • java中Thread.sleep()函数使用

    万次阅读 多人点赞 2015-10-13 18:05:03
    我们可能经常会用到 Thread.Sleep 函数来使线程挂起一段时间。那么你有没有正确的理解这个函数的用法呢?思考下面这两个问题: 假设现在是 2008-4-7 12:00:00.000,如果我调用一下 Thread.Sleep(1000) ,在 2008-...
  • java中的daemon thread

    千次阅读 2020-03-18 09:07:39
    java中的daemon thread java中有两种类型的thread,user threads 和 daemon threads。 User threads是高优先级的thread,JVM将会等待所有的User Threads运行完毕之后才会结束运行。 daemon threads是低优先级的...
  • 怎么在java中关闭一个thread

    千次阅读 2020-03-15 09:51:53
    怎么在java中关闭一个thread 我们经常需要在java中用到thread,我们知道thread有一个start()方法可以开启一个线程。那么怎么关闭这个线程呢? 有人会说可以用Thread.stop()方法。但是这个方法已经被废弃了。 根据...
  • Java中使用Thread

    千次阅读 2018-07-17 15:12:45
    那么JVM就要在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源,main方法即使执行完最后的语句(主线程结束),JVM也不会结束Java应用程序,JVM一直要等到Java应用程序的所有线程都结束之后,才会...
  • java编译出现了Exception in thread “main” java.lang.UnsupportedClassVersionError起因: StringBuilder不能赋值?不对,错误原因是因为下面报错的log: 搜了下答案,参考 百度知道:java编译出现了...
  • Java中Runnable和Thread的区别

    万次阅读 热门讨论 2018-02-28 18:03:53
    概述Runnable 是接口。Thread 是类,且实现了...Thread部分源码[java] view plain copypublic class Thread implements Runnable { private static class Caches { static final ConcurrentMap su...
  • Java中Synchronized的用法

    万次阅读 多人点赞 2015-06-24 00:25:01
    synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种: 1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象; 2. 修饰一...
  • JAVA中Thread.currentThread是什么意思

    万次阅读 2017-06-02 16:19:45
    当年学的时候,我也纳闷,为什么获取当前线程需要调用Thread类的静态方法去获取,为毛不直接用对象操作就行了啊?上代码先:class MyThread extends Thread { @Override public void run() { try { Thread.sleep...
  • java中线程的生命周期

    万次阅读 2020-03-13 10:07:45
    文章目录java中Thread的状态NEWRunnableBLOCKEDWAITINGTIMED_WAITINGTERMINATED java中线程的生命周期 线程是java中绕不过去的一个话题, 今天本文将会详细讲解java中线程的生命周期,希望可以给大家一些启发。 java...
  • javaThread Dump分析

    千次阅读 2017-08-20 23:04:25
    每一个Java虚拟机都有及时生成所有线程在某一点状态的thread-dump的能力,虽然各个 Java虚拟机打印的thread dump略有不同,但是大多都提供了当前活动线程的快照,及JVM所有Java线程的堆栈跟踪信息,堆栈信息一般...
  • JavaThread的join()方法原理

    万次阅读 多人点赞 2018-05-09 18:34:09
    简介 join()是Thread类的一个方法。根据jdk文档的定义: public final void join()throws InterruptedException: Waits for this thread to die. ...个人认为”Java 7 Concurrency Cookbook”的定义较为...
  • 当线程是RUNNABLE时,它可以正在运行,也可以不运行....Java doc线程的所有状态: java.lang public class Thread.State extends Enum A thread state. A thread can be in one of the fol...
  • 最近在Linux上的eclipse运行java程序出现了这样的错误,弄了很久用了以下三种方法终后终于成功运行了,分享下,希望能帮助到大家。 Linux运行java程序提示错误: Exception in thread &amp;quot;main&...
  • Java Thread 实现方式

    千次阅读 2018-05-09 08:45:45
    答案是调用run()的线程,因为只有在调用start()之后,Java才会创建一个新的线程,然后新的线程再调用执行Java代码里面的run()。看如下代码,一个简单的实现:Thread thread = new Thread(){ public...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,072,796
精华内容 429,118
关键字:

java中thread

java 订阅