zoukankan      html  css  js  c++  java
  • Java线程机制

    线程简介:

    线程是一个程序内部的顺序控制流。
    线程和进程的区别:
      每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销。
      线程可以看成是轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器,线程切换的开销小。

    多进程:
      在操作系统中能同时运行的多个任务。
    多线程:
      在同一个应用程序中有多个顺序流同时执行。

    Java的线程是通过java.lang.Thread类实现的;JVM启动时会有一个由主方法所定义的线程;可以通过创建Thread的实例来创建新的线程;每个线程都是通过某个特定的Thread对象所对应的run()方法来完成其操作的,run()方法称为线程体。

    线程的创建与启动:

    第一种:
      1.定义线程类target实现Runnable接口(使用Runnable接口可以为多个线程提供共享数据),其中Runnable中只有一个方法public void run();
      2.Thread my Thread = new Thread(target);
      3.在实现Runnable接口的类的run()方法定义中可以使用Thread的静态方法(currectThread()方法用于获取当前线程的引用)。
    第二种:
      1.可以定义一个Thread的子类并重写其run()方法:class MyThread extends Thread{ public void run(){ } } ;
      2.然后生成该类的对象。

    线程状态的转换:

                           阻塞解除    
                      <-----------------
                       调度     导致阻塞的事件
                      <----       ---->*阻塞状态
      *创建    *就绪状态    *运行状态     *终止
          ---->       ---->       ---->
          start        调度       运行结束

    *标记为线程状态,箭头表示转换过程。

    线程控制的基本方法:

    isAlive()        判断线程是否还活着,即线程还未终止(上面的阻塞、就绪、运行三个状态)
    getPriority()      获得线程的优先级
    setPriority()      设置线程的优先级
    Thread.sleep()      使当前线程进入休眠状态,并指定睡眠的毫秒数
    join()          将当前线程与被调用该方法的线程合并,即等待该线程结束,在回复当前线程的运行
    yield()         让出cpu,当前线程进入就绪队列等待调度
    wait()          当前线程进入对象的wait pool
    notify()/notifyAll()    唤醒对象的wait pool中的一个/所以等待线程

    join的例子:

    public class TestJoin {
      public static void main(String[] args) {
        MyThread2 t1 = new MyThread2("abcde");
        t1.start();
        try {
            t1.join();
        } catch (InterruptedException e) {}
            
        for(int i=1;i<=10;i++){
          System.out.println("i am main thread");
        }
      }
    }
    class MyThread2 extends Thread {
      MyThread2(String s){
          super(s);
      }
      
      public void run(){
        for(int i =1;i<=10;i++){
          System.out.println("i am "+getName());
          try {
              sleep(1000);
          } catch (InterruptedException e) {
              return;
          }
        }
      }
    }

    只有执行完了t1的run()方法时才会继续执行main()方法。

    Java的优先级别:

    Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照线程的优先级决定应调用哪个线程来执行;线程的优先级用数字来表示,范围从1到10,一个线程的缺省优先级是5。
      Thread.MIN_PRIORITY = 1
      Thread.MAX_PRIORITY = 10
      Thread.NORM_PRIORITY = 5

    线程同步:

      在Java语言中,引入对象互斥锁的概念,保证共享数据操作的完整性;每个对象都对应于一个可以成为互斥锁的标记;这个标记保证在任意时刻,只有一个线程访问该对象;关键字synchronized用来与对象的互斥锁相联系;当某个对象的synchronized修饰时,表明该对象在任一时刻只能由一个线程访问。


    synchronized的用法:

          synchronized (this) {
    
          }

    synchronized还可以放在方法生声明中,表示整个方法为同步方法:

      public synchronized void add(String name){ 
    
      }

    无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。

    public class TestSync implements Runnable {
      Timer timer = new Timer();
      public static void main(String[] args) {
        TestSync test = new TestSync();
        Thread t1 = new Thread(test);
        Thread t2 = new Thread(test);
        t1.setName("t1"); 
        t2.setName("t2");
        t1.start(); 
        t2.start();
      }
      public void run(){
        timer.add(Thread.currentThread().getName());
      }
    }
    
    class Timer{
      private static int num = 0;
      public synchronized void add(String name){ 
          //synchronized (this) {
            num ++;
            try {Thread.sleep(1);} 
            catch (InterruptedException e) {}
            System.out.println(name+", 你是第"+num+"个使用timer的线程");
          //}
      }
    }

    需要注意的是:

      1.两个线程不可同时执行一个类中被声明了synchronized的方法;
      2.当一个线程正在访问一个类的其中一个被声明为synchronized方法的方法的时候,其他线程可以访问该类中没有声明为synchronized的方法;
      3.一个类中不可以同时有多个被声明为synchronized的方法被执行(一个对象只有一个互斥锁,需要等待另外一个线程释放互斥锁后才可以执行)。

    Wait和sleep的区别:

      Wait时,别的线程可以访问锁定的对象(调用wait的方法的时候必须锁定该对象)。
      Sleep时,别的线程不可以访问锁定对象。

    死锁的例子:

    public class TestDeadLock implements Runnable {
        public int flag = 1;
        static Object o1 = new Object(), o2 = new Object();
        public void run() {
    System.out.println("flag=" + flag);
            if(flag == 1) {
                synchronized(o1) {
                    try {
                        Thread.sleep(500);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    synchronized(o2) {
                        System.out.println("1");    
                    }
                }
            }
            if(flag == 0) {
                synchronized(o2) {
                    try {
                        Thread.sleep(500);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    synchronized(o1) {
                        System.out.println("0");
                    }
                }
            }
        }    
        
        public static void main(String[] args) {
            TestDeadLock td1 = new TestDeadLock();
            TestDeadLock td2 = new TestDeadLock();
            td1.flag = 1;
            td2.flag = 0;
            Thread t1 = new Thread(td1);
            Thread t2 = new Thread(td2);
            t1.start();
            t2.start();
            
        }
    }


  • 相关阅读:
    hdu 1695 GCD 欧拉函数 + 容斥
    E. Xenia and Tree 分块 + LCA
    二分图匹配 + 构造 E. Arpa’s overnight party and Mehrdad’s silent entering
    Win系统如何修改远程桌面端口3389
    centos7下使用selenium实现文件上传
    windows下tesseract-ocr的安装及使用
    windows下pycharm输入法跟随设置
    django 外键使用select html
    xstart访问centos7
    Centos7 安装VNC实现远程桌面
  • 原文地址:https://www.cnblogs.com/mosquito-woo/p/3920348.html
Copyright © 2011-2022 走看看