zoukankan      html  css  js  c++  java
  • Thread

    线程创建:

    1继承Thread类

    public class ThreadC extends Thread {
    
        private MyService myService;
    
        ThreadC(MyService service) {
            myService = service;
        }
    
        @Override
        public void run() {
            MyService.printA();
        }
    }

    2实现Runnable接口

    public class ThreadA implements Runnable {
    
        private MyService myService;
    
        ThreadA(MyService service) {
            myService = service;
        }
    
        @Override
        public void run() {
            MyService.printA();
        }
    }
    //执行
    ThreadA threadA = new ThreadA(myService);
    Thread thread1 = new Thread(threadA);
    thread1.start();

    3线程池:通过线程池创建线程

    4线程的方法:

    Thread thread1 = new Thread(threadA);
    thread1.start();
    thread1.wait();//释放锁!!既然是释放锁,所以需要先加锁 ->synchronized
    thread1.notify();//唤醒被wait的!!需要先加锁 ->synchronized
    thread1.suspend();//挂起线程不释放锁,仅仅是暂停线程的执行,容易导致死锁,因为该线程在暂停的时候仍然占有该资源,这会导致其他需要该资源的线程与该线程产生环路等待,从而造成死锁。
    thread1.resume(); //resume() 方法后,被挂起的suspend线程才能继续,从而其它被阻塞在这个锁的线程才可以继续执行。

    thread1.interrupt();//停止线程 
    thread1.isInterrupted();//是否是停止状态
    thread1.isAlive();//是否是活的状态
    Thread.yield();//放弃当前CPU资源,让其他任务去占用CPU执行时间,但放弃时间不确定,可能刚刚放弃,马上又来获取CPU时间片。

    thread1.stop();//该方法在终结一个线程时不会保证线程的资源正常释放,通常是没有给予线程完成资源释放工作的机会,因此会导致程序在可能在工作状态不确定的情况下工作。
    suspend和resume会导致:
    1线程独占,使其他对象无法访问公共同步对象
    2数据不同步

    线程停止:

    5线程间通信:

    1 wait/notify

    2 共享一个变量,去判断状态来执行

    6线程切换:

     

    线程切换示意图

    概括的解释下线程的几种可用状态。

    新建( new ):新创建了一个线程对象;

    可运行( runnable ):线程对象创建后,其他线程(比如 main 线程)调用了该对象的 start ()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获 取CPU的使用权;

    运行( running ):可运行状态( runnable )的线程获得了CPU时间片( timeslice ) ,执行程序代码;

    阻塞( block ):阻塞状态是指线程因为某种原因放弃了CPU 使用权,也即让出了 CPU timeslice ,暂时停止运行。直到线程进入可运行( runnable )状态,才有 机会再次获得 cpu timeslice 转到运行( running )状态。

    阻塞的情况分三种:

    1. 等待阻塞:运行( running )的线程执行 o . wait ()方法, JVM 会把该线程放 入等待队列( waitting queue )中。

    2. 同步阻塞:运行( running )的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则 JVM 会把该线程放入锁池( lock pool )中。

    3. 其他阻塞: 运行( running )的线程执行 Thread . sleep ( long ms )或 t . join ()方法,或者发出了 I / O 请求时, JVM 会把该线程置为阻塞状态。当 sleep ()状态超时、 join ()等待线程终止或者超时、或者 I / O 处理完毕时,线程重新转入可运行( runnable )状态。

    死亡( dead ):线程 run ()、 main () 方法执行结束,或者因异常退出了 run ()方法,则该线程结束生命周期。死亡的线程不可再次复生。

    同步方法和同步代码块的区别是什么?

    区别:

    • 同步方法默认用this或者当前类class对象作为锁;

    • 同步代码块可以选择以什么来加锁,比同步方法要更细颗粒度,我们可以选择只同步会发生同步问题的部分代码而不是整个方法;

    在监视器(Monitor)内部,是如何做线程同步的?程序应该做哪种级别的同步?

    监视器和锁在Java虚拟机中是一块使用的。监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许执行同步代码。

    java 还提供了显式监视器( Lock )和隐式监视器( synchronized )两种锁方案。

    什么是死锁(deadlock)?

    两个线程或两个以上线程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是这些线程都陷入了无限的等待中。

    如何确保N个线程可以访问N个资源同时又不导致死锁?

    多线程产生死锁的四个必要条件:

    • 互斥条件:一个资源每次只能被一个进程使用。

    • 保持和请求条件:一个进程因请求资源而阻塞时,对已获得资源保持不放。

    • 不可剥夺性:进程已获得资源,在未使用完成前,不能被剥夺。

    • 循环等待条件(闭环):若干进程之间形成一种头尾相接的循环等待资源关系。

    只要破坏其中任意一个条件,就可以避免死锁

    一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。

  • 相关阅读:
    C# 使用自带Microsoft.Office.Interop.Excel简单操作Excel文件
    Winform修改配置文件节点保存到配置文件
    C# MD5加密字符串
    dev gridcontrol简单的动态设置动态表头
    dev gridcontrol绘制页脚
    dev gridcontrol 导出到excel
    dev gridcontrol设置过滤器下拉列表
    为什么要使用Unix时间戳
    DataTable和DataReader的遍历
    C#生成不重复随机数的方法
  • 原文地址:https://www.cnblogs.com/fanBlog/p/11342183.html
Copyright © 2011-2022 走看看