zoukankan      html  css  js  c++  java
  • 线程

    线程终止

    ① 因为 run 方法正常退出而自然死亡
    ② 因为一个没有捕获的异常终止了 run 方法而意外死亡
    

    线程状态

    线程优先级

    每一个线程有一个优先级。默认情况下, 一个线程继承它的父线程的优先级。 可以用 setPriority 方法提高或降低任何一个线程的优先级。可以将优先级设置为在 MIN_PRIORITY (在 Thread 类中定义为 1 ) 与 MAX_PRIORITY (定义为 10 ) 之间的任何值。NORM_PRIORITY 被定义为 5。

    创建一个线程方式

    方式一:继承Thread类

    /**
    步骤:
      1. 声明一个类,让其继承Thread类,该类成为子类
      2. 重写Thread类的run方法 
      3. 调用该类 的 实例并 start
    public static void main(String[] args) {
            MyThread myThread = new MyThread();
            //start() 作用: 
            /**
              Causes this thread to begin execution;  执行该线程
              the Java Virtual Machine calls the run method of this thread. 调用 当前线程 run
            */
            myThread.start();
    }
    
    class MyThread extends Thread{
        @Override
        public void run() {
            //do something
            System.out.println("具体处理");
        }
    }
    
    // 线程常用方法
    System.out.println(MyThread.currentThread()); Thread[main,5,main]
    System.out.println(myThread.getName());  Thread-0
    

    方式一的卖票问题

    
    public class ThreadTest {
        public static void main(String[] args) {
            Ticket ticket = new Ticket();
            ticket.start();
    
            Ticket ticket1 = new Ticket();
            ticket1.start();
    
            Ticket ticket2 = new Ticket();
            ticket2.start();
    
        }
    }
    class Ticket extends Thread{
        static int ticket = 10;
        @Override
        public void run() {
    
            while (true){
                if (ticket > 0){
                    System.out.println(Thread.currentThread().getName()+"票数:"+ticket);
                    ticket--;
                }else {
                    break;
                }
            }
        }
    }
    /**
    结果:
    Thread-0票数:5
    Thread-0票数:4
    Thread-0票数:3
    Thread-0票数:2
    Thread-0票数:1
    Thread-1票数:5
    Thread-2票数:5
    */
    

    方式二:实现Runnable接口

    
    /**
       1. 编写一个类 实现Runnable接口
       2. 实现接口中run方法
       3. 创建该类对象,把此对象当作参数传递给Thread构造器中,创建Thread对象
       4. 通过Thread对象调用start方法
     public static void main(String[] args) {
            MyThread2 myThread2 = new MyThread2();
            Thread thread = new Thread(myThread2);
            thread.start();
        }
    }
    class MyThread2 implements Runnable{
        @Override
        public void run() {
            //doSomething
            System.out.println("doSomething");
        }
    }
    */
    

    方式二的卖票问题

    
    public class ThreadTest1 {
        public static void main(String[] args) {
            Target2 target2 = new Target2();
            Thread thread = new Thread(target2);
            thread.start();
    
            Thread thread1 = new Thread(target2);
            thread1.start();
    
            Thread thread2 = new Thread(target2);
            thread2.start();
        }
    }
    class Target2 implements Runnable{
        int target2 = 5;
        @Override
        public void run() {
            //doSomething
            while (true){
                if (target2 > 0){
                    System.out.println(Thread.currentThread().getName()+"票数:"+target2);
                    target2--;
                }else {
                    break;
                }
            }
        }
    }
    /**
     结果:
    Thread-0票数:5
    Thread-0票数:4
    Thread-0票数:3
    Thread-0票数:2
    Thread-2票数:5
    Thread-2票数:1
    Thread-1票数:5
    */
    

    创建线程的第三种方式Callable-尚未补充

    //待补充
    

    创建线程的第四种方式 线程池:Executors-尚未补充

    //待补充
    

    线程安全-synchronized方式

    /**
    对两种创建线程的方式 进行加锁处理,该处理有两种解决方案,
    同步代码块和同步方法。
    对共享的代码进行加锁处理,多个线程需要共用一把锁
    */
    public class ThreadTest1 {
        public static void main(String[] args) {
            Target2 target2 = new Target2();
            Thread thread = new Thread(target2);
            thread.start();
    
            Thread thread1 = new Thread(target2);
            thread1.start();
    
            Thread thread2 = new Thread(target2);
            thread2.start();
        }
    }
    class Target2 implements Runnable{
        int target2 = 5;
        @Override
        public void run() {
            //doSomething
            while (true){
                synchronized (this){ //this表示当前对象,在此处且唯一
                    if (target2 > 0){
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+"票数:"+target2);
                        target2--;
                    }else {
                        break;
                    }
                }
            }
        }
    }
    /** 结果:
    Thread-1票数:5
    Thread-1票数:4
    Thread-1票数:3
    Thread-1票数:2
    Thread-1票数:1
    */
    
    
    public class ThreadTest {
        public static void main(String[] args) {
            Ticket ticket = new Ticket();
            ticket.start();
    
            Ticket ticket1 = new Ticket();
            ticket1.start();
    
            Ticket ticket2 = new Ticket();
            ticket2.start();
    
        }
    }
    class Ticket extends Thread{
        static int ticket = 5;
        private static Object o = new Object(); //对象o唯一
        @Override
        public void run() {
    
            while (true){
                synchronized (o){ //o可替换为 Ticket.class
                    if (ticket > 0){
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+"票数:"+ticket);
                        ticket--;
                    }else {
                        break;
                    }
                }
            }
        }
    }
    /** 结果:
    Thread-0票数:5
    Thread-0票数:4
    Thread-0票数:3
    Thread-0票数:2
    Thread-0票数:1
    */
    
    // 也可用同步方法改写,把共享代码写入一个方法中,加synchronized关键字即可。如:
    public synchronized void methodName(){};
    

    线程安全-Reentrant 方式

    // 用 ReentrantLock 保护代码块的基本结构如下:
    myLock.lock(); // a ReentrantLock object
    try{
        critical section
    }
    finally{
        myLock.unlockO;// make sure the lock is unlocked even if an exception is thrown
    }
    

    example

    public class ReentrantTest {
        public static void main(String[] args) {
            test1();
        }
    
        public static void test1(){
            Ticket2 ticket2 = new Ticket2();
    
            Thread thread = new Thread(ticket2);
            thread.start();
    
            Thread thread1 = new Thread(ticket2);
            thread1.start();
    
            Thread thread2 = new Thread(ticket2);
            thread2.start();
        }
    }
    class Ticket2 implements Runnable{
    
        private int ticket = 100;
        private ReentrantLock lock = new ReentrantLock(); //第三种方式
    
        @Override
        public void run() {
            while (true){
                try {
                    lock.lock();  //锁住
                    if (ticket > 0){
                        System.out.println(Thread.currentThread().getName()+"票数:"+ticket);
                        ticket--;
                    }else {
                        break;
                    }
                }finally {
                    lock.unlock();  //开锁
                }
            }
        }
    }
    

    synchronized 和 ReentrantLock的区别

    ReentrantLock 需要手动上锁 和 手动解锁

    条件对象 Condition

    待补充

    线程通信

    /**
      wait(): 表示 当前线程进入 阻塞 状态,并释放同步监视器
      notify(): 唤醒 被阻塞(wait)的线程,若有多个线程被阻塞,则唤醒优先级高的线程
      notifyAll(): 唤醒所有被阻塞的线程
    这三个方法必须 放在同步代码块和同步方法中;
    这三个方法必须是同步代码块或同步方法中和监视器同一个对象;
    这三个方法都位于Object类中
    */
    public class ReentrantTest {
        public static void main(String[] args) {
            test2();
        }
    
        public static void test2(){
            Clock c1 = new Clock();
            c1.start();
    
            Clock c2 = new Clock();
            c2.start();
        }
    }
    
    class Clock extends Thread{
        private static int count = 10;
    
        @Override
        public void run() {
            while (true){
                synchronized (Clock.class){
                    Clock.class.notify(); //表示 唤醒被阻塞(wait())的线程;notifyAll: 唤醒所有阻塞线程
                    if (count >= 0){
                        System.out.println(Thread.currentThread().getName()+"	"+count);
                        count--;
                        try {
                            Clock.class.wait(); //wait和notify需要和监视器一致
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else {
                        break;
                    }
                }
            }
        }
    }
    

    sleep 和 wait 异同

      - 都可以表示 线程 阻塞
      - sleep 位于 Thread类中,wait位于Object类中
      - sleep 任何 场景调用,wait 只能在同步代码块或同步方法中调用
      - 若两个方法都用在了 同步代码块或同步方法中,则wait 可以释放同步监视器,sleep不会释放同步监视器
  • 相关阅读:
    linux(unix)下.tar.gz解压
    linux 实验室
    Liferea 1.0.15
    编造机中鼠标无法应用标题问题解答
    GnuCash 1.9.8
    KDE 走向跨平台, 支持 Windows 和 Mac OS X
    KDVDCreator:创立视频 VCD、SVCD 和 DVD
    digiKam 0.9.3 颁布公布
    Sysinfo 0.7beta4
    KDE 4.1 特性及公布筹划
  • 原文地址:https://www.cnblogs.com/huyuqing/p/14343396.html
Copyright © 2011-2022 走看看