Java 线程

目录

1、线程状态

1.1、Blocked

1.2、Time_waited/Waiting

2、主线程和子线程

2.1、start和run

2.2、主线程结束后不影响子线程

2.3、主线程等待子线程结束后结束

2.4、主线程结束后子线程(守护线程)立即终止

2.5、守护线程

3、sleep和wait

3.1、sleep

3.2、wait

4、线程相关方法

4.1、join

4.2、yield

4.3、interrupt,isInterrupted,interrupted

4.4、stop

4.5、suspend/resume

5、volatile


 

1、线程状态

public enum State {
         start之前
        NEW,

         可运行线程的线程状态。处于可运行状态的线程正在Java虚拟机中执行,
         但它可能正在等待来自操作系统(如处理器)的其他资源。
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

1.1、Blocked

public class MainTest {
    public static void main(String[] args) throws InterruptedException {
        class Counter {
            int counter;
            public synchronized void increase() {
                counter++;
                try {
                    Thread.sleep(30000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }

        Counter c = new Counter();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                c.increase();
            }
        }, "t1线程");
        t1.start();

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                c.increase();
            }
        }, "t2线程");
        t2.start();

        Thread.sleep(100); // 确保 t2 run已经得到执行
        System.out.println(t2.getState());
    }
}

BLOCKED

1.2、Time_waited/Waiting

public class DemoThread extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " run " + Thread.currentThread().getState());
        super.run();
        try {
            Thread.sleep(3000);
             waitEx(); waiting状态
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public synchronized void start() {
        System.out.println(Thread.currentThread().getName() + " start " + Thread.currentThread().getState());
        super.start();
    }

    @Override
    public State getState() {
        return super.getState();
    }

    public synchronized void waitEx() throws InterruptedException {
        wait();
        System.out.println(Thread.currentThread().getName() + " waitEx " + Thread.currentThread().getState());
    }

    public synchronized void notifyEx() {
        notify();
        System.out.println(Thread.currentThread().getName() + " notifyEx " + Thread.currentThread().getState());
    }
}
public class MainTest {
    public static void main(String[] args) throws InterruptedException {
        DemoThread demoThread = new DemoThread();
        System.out.println(demoThread.getState());
        demoThread.start();
        Thread.sleep(100);
        System.out.println(demoThread.getState());
        demoThread.notifyEx();
        System.out.println(demoThread.getState());
    }
}


NEW
main start RUNNABLE
Thread-0 run RUNNABLE
WAITING
main notifyEx RUNNABLE
Thread-0 waitEx RUNNABLE
TERMINATED

2、主线程和子线程

2.1、start和run

  • 首先new Thread()出来的对象会分配一个线程名称
  • start:来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码;通过调用Thread类的start()方法来启动一个线程, 这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行操作的, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。然后CPU再调度其它线程。
  • run:相当于普通方法调用。程序还是会顺序执行,要等待run方法体执行完毕后,才可继续执行下面的代码; 程序中只有主线程——这一个线程, 其程序执行路径还是只有一条, 这样就没有达到写线程的目的。
public static void main(String[] args) throws InterruptedException {
    new Thread(){
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }.start();
}

结果:
Thread-0
public static void main(String[] args) throws InterruptedException {
    new Thread(){
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }.run();
}

结果:
main
public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    });
    thread.run();
    System.out.println(thread.getName());
}

结果:
main
Thread-0

2.2、主线程结束后不影响子线程

public class SubThread implements Runnable {
    @Override
    public void run() {
        try {
            System.out.println("子线程启动");
            Thread.sleep(5000);
            System.out.println("子线程结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public static void main(String[] args) throws InterruptedException {
    System.out.println("主线程启动");
    Thread thread = new Thread(new SubThread());
    thread.start();
    Thread.sleep(100);
    System.out.println("主线程结束");
}

结果:
主线程启动
子线程启动
主线程结束
子线程结束

2.3、主线程等待子线程结束后结束

public class SubThread implements Runnable {
    @Override
    public void run() {
        try {
            System.out.println("子线程启动");
            Thread.sleep(1000);
            System.out.println("子线程结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class TestMain {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("主线程启动");
        Thread thread = new Thread(new SubThread());
        thread.start();
        thread.join();
        Thread.sleep(100);
        System.out.println("主线程结束");
    }
}

结果:
主线程启动
子线程启动
子线程结束
主线程结束

2.4、主线程结束后子线程(守护线程)立即终止

子线程需要设置守护线程

public class SubThread implements Runnable {
    @Override
    public void run() {
        try {
            System.out.println("子线程启动");
            Thread.sleep(1000);
            System.out.println("子线程结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class MainTest {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("主线程启动");
        Thread thread = new Thread(new SubThread());
        thread.setDaemon(true);
        thread.start();
        Thread.sleep(100);
        System.out.println("主线程结束");
    }
}


结果:
主线程启动
子线程启动
主线程结束

2.5、守护线程

用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守护线程的保姆:

只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器),它就是一个很称职的守护者。

User和Daemon两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果 User Thread已经全部退出运行了,只剩下Daemon Thread存在了,虚拟机也就退出了。 因为没有了被守护者,Daemon也就没有工作可做了,也就没有继续运行程序的必要了。

3、sleep和wait

3.1、sleep

sleep()方法是线程类(Thread)的静态方法,使得当前线程进入阻塞状态,给执行机会给其他线程(实际上,调用sleep()方法时并不要求持有任何锁,即sleep()可在任何地方使用。),但是监控状态依然保持,到时后会自动恢复。

当线程处于上锁时,sleep()方法不会释放对象锁,只会让出CPU执行时间片。休眠时间满后,该线程不一定会立即执行,等待CPU调度。

3.2、wait

wait()方法是Object类里的方法,当一个线程执行wait()方法时,它就进入到一个和该对象相关的等待池中(进入等待队列,也就是阻塞的一种,叫等待阻塞),同时释放对象锁,并让出CPU资源,待指定时间结束后返还得到对象锁。

wait()使用notify()方法、notiftAll()方法唤醒当前等待池中的线程。等待的线程只是被激活,但是必须得再次获得锁才能继续往下执行。wait()方法、notify()方法和notiftAll()方法用于协调多线程对共享数据的存取,所以只能在同步方法或者同步块中使用,否则抛出IllegalMonitorStateException。

4、线程相关方法

4.1、join

调用isAlive()判断形成是否活跃,活跃则调用wait()方法等待,活跃是native方法(子线程都在运行则活跃

public final synchronized void join(long millis) throws InterruptedException {
    long base = System.currentTimeMillis();
    long now = 0;

    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (millis == 0) {
        while (isAlive()) {
            wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

public final native boolean isAlive();

4.2、yield

让出同优先级线程的CPU时间片

public static native void yield();

4.3、interrupt,isInterrupted,interrupted

  • interrupt():在一个线程中调用另一个线程的interrupt()方法,即会向那个线程发出信号——线程中断状态已被设置。至于那个线程何去何从,由具体的代码实现决定
  • isInterrupted():用来判断当前线程的中断状态(true or false)
  • interrupted():是个Thread的static方法,用来恢复中断状态
public class MethodThread extends Thread {
    @Override
    public void run() {
        super.run();
        try {
            long start = System.currentTimeMillis();
            int i = 0;
            for (; i < 1000000; i++) {
                String str0 = "0";
                String str1 = "1";
                String str2 = "2";
                String str3 = "3";
                String str4 = "4";
                String str5 = "5";
                String str6 = "6";
                String str7 = "7";
                String str8 = "8";
                String str9 = "9";
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("interrupt");
                    Thread.interrupted();
                    System.out.println(Thread.currentThread().isInterrupted());
                }
            }
            System.out.println((System.currentTimeMillis()-start)+" end " + i);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public class MainTest{
    public static void main(String[] args) throws InterruptedException {
        MethodThread methodThread = new MethodThread();
        methodThread.start();
        Thread.sleep(1);
        System.out.println(methodThread.isInterrupted());
        methodThread.interrupt();
    }
}

结果:
false
interrupt
false
16 end 1000000

4.4、stop

方法已废除

  • 即刻停止run()方法中剩余的全部工作,包括在catch或finally语句中,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭
  • 会立即释放该线程所持有的所有的锁,导致数据得不到同步的处理,出现数据不一致的问题

4.5、suspend/resume

方法已废除

suspend()和resume()必须要成对出现,否则非常容易发生死锁。 

因为suspend方法并不会释放锁,如果使用suspend的目标线程对一个重要的系统资源持有锁,那么没任何线程可以使用这个资源直到要suspend的目标线程被resumed,如果一个线程在resume目标线程之前尝试持有这个重要的系统资源锁再去resume目标线程,这两条线程就相互死锁了,也就冻结线程。

public class Main{
    public static void main(String [] args) throws Exception{
        TestObject testObject = new TestObject();
        Thread t1 = new Thread(){
            public void run(){
                testObject.print();
            }
        };
        t1.setName("A");
        t1.start();
        Thread.sleep(1000);
 
        Thread t2 = new Thread(){
            public void run(){
                System.out.println("B已启动,但进入不到print方法中");
                testObject.print();
            }
        };
        t2.setName("B");
        t2.start();
    }
}
 
class TestObject{
    public synchronized void print(){
        if(Thread.currentThread().getName().equals("A")){
            System.out.println("A 线程 独占该资源了");
            Thread.currentThread().suspend();
        }
    }
}

结果:
A 线程 独占该资源了
已启动,但进入不到print方法中

5、volatile

volatile让变量每次在使用的时候,都从主存中取。而不是从各个线程的“工作内存”。

volatile具有synchronized关键字的“可见性”,但是没有synchronized关键字的“并发正确性”,就是说不保证线程执行的有序性。

volatile变量对于每次使用,线程都能得到当前volatile变量的最新值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值