• 2017年4月14号课堂笔记


    2017年4月14号  星期五 空气质量:重度污染

    内容:多线程第一节课

    一、进程、线程和多线程

    老师代码:

    package cn.bdqn.util;

    public class ReadeMe {
    /**
    *
    * 进程:由一个或者多个线程组成!
    * 应用程序(QQ,微信)的执行实例!有自己独立的内存空间和系统资源!
    *
    * 线程: cpu真正执行的是 线程!是cpu调度和分配的最基本的单位!
    *
    * 我们感觉是同一个时间点,cpu在运行多个程序!----》多线程!
    * 因为cpu在一个时间点,只能执行一个线程!
    * 多线程交替占用cpu的资源!并不是真正的同时执行多个线程!
    *
    * 例子:
    * 01. 现在地铁有5个进站口! 有5个人 可以 同时(看着像同时)进站!
    * 02. 现在地铁有1个进站口! 有5个人 必须 排队 进站!
    * 问题?
    * 哪个效率高? 01效率高!
    *
    * 地铁 : CPU
    * 进站口:线程
    *
    * 多线程的好处:
    * 01.充分利用cpu的资源
    * 02.给用户带来良好的体验
    *
    *
    */

    package cn.bdqn.thread;

    public class MyThread {

    public static void main(String[] args) {
    // 获取当前执行的线程
    Thread t = Thread.currentThread();
    System.out.println(t);
    /**
    * t的输出:Thread[main,5,main]
    * 01.按理说应该输出的是 全类名+@+hash
    * 02.但是输出的是Thread[main,5,main]
    * 03.可以断定 Thread重写了 Object类中的toString()
    * main:主线程的名称
    * 5:当前线程的优先级 默认是5,最小是1,最大是10
    * main:所属线程组的名称
    */
    // 更改当前线程的名称
    t.setName("主线程");
    System.out.println("当前线程的名称是:" + t.getName());
    System.out.println(t);
    }

    }

    }

    二、实现多线程的两种方式之一(继承Thread类)及start和run的区别

    老师代码:

    package cn.bdqn.thread01;

    /**
    * 实现多线程 的方式:
    * 01.类 继承Thread类,并且重写Thread中的run()方法!
    */
    public class MyThread extends Thread {

    // 重写Thread中的run()方法! 是普通的方法!
    @Override
    public void run() {
    for (int i = 1; i <= 10; i++) {
    // 输出当前线程的名称 +i
    System.out.println(Thread.currentThread().getName() + "====>" + i);
    }
    }

    // 主线程
    public static void main(String[] args) {

    /** 实例化线程类
    * 01.创建了2个线程类对象
    * 02.分别执行run()
    * 03.run()本身就是一个普通的方法,并不是代表启动线程!
    * 04.thread1.run() 这时候对象1 先执行run() 执行完毕 再执行对象2的run()
    * MyThread thread1 = new MyThread();
    * MyThread thread2 = new MyThread();
    * thread1.run();
    * thread2.run();
    */
    MyThread thread1 = new MyThread();
    MyThread thread2 = new MyThread();
    thread1.setName("线程111");
    thread2.setName("线程222");
    thread1.start(); // 电脑上双击QQ
    thread2.start(); // 电脑上双击微信
    /**
    * 01.创建了2个线程类对象
    * 02.分别执行start(),代表线程开启
    * 03.线程开启,就代表两个线程会交替执行!
    * 问题:
    * thread1.start(); 能保证对象1就先执行吗? 不能!
    */
    }
    /**
    * start 和 run 的区别!
    *
    * run:普通的方法!也成为线程体!cpu分配时间片给当前线程的时候,线程才会真正的执行!
    *
    * start:我们所写的线程类中并没有start(),但是父类中有!继承父类的方法!
    * 启动线程!不是线程的执行,在调用start方法的时候,底层默认会执行run()!
    *
    *

    }


     

    三、实现多线程的两种方式之二(实现Runnable接口)

     老师代码:

    package cn.bdqn.runnable02;

    /**
    * 02.实现 Runnable接口 重写 run()
    *
    */
    public class MyThread implements Runnable {

    // 重写Thread中的run()方法! 是普通的方法!
    @Override
    public void run() {
    for (int i = 1; i <= 10; i++) {
    // 输出当前线程的名称 +i
    System.out.println(Thread.currentThread().getName() + "====>" + i);
    }
    }

    // main 主线程
    public static void main(String[] args) {
    // 创建线程对象
    MyThread thread = new MyThread();
    // 发现没有 Start()
    Thread thread1 = new Thread(thread);
    Thread thread2 = new Thread(thread);
    // 开启线程
    thread1.start();
    thread2.start();

    }

    }

    四、线程的生命周期(附带图示)

    老师代码:

    * 线程的生命周期!

    * 01.新生状态
    * MyThread thread1 = new MyThread();
    * 02.就绪状态
    * thread1.start(); 
    * 03.运行状态
    * cpu分配时间片给thread1的时候,开始执行run()
    * 04.阻塞状态
    * sleep(),wait(),join(),yield();
    * 05.死亡状态
    * 01.正常死亡 run()执行完毕
    * 02.异常死亡 run()执行过程中,出现异常退出的情况!

    */

    五、线程的阻塞状态(interrupted)

    老师代码:

    package cn.bdqn.interrupted03;

    /**
    *
    线程的阻塞状态
    01.InterruptedException(见第六部分)
    02.sleep 和 wait 的区别(见第七部分)
    001.sleep 在 Thread类中,wait 在Object类中
    002.sleep休眠,占用cpu资源,不释放锁!后续线程等待! 使用interrupted()唤醒
    003.wait 等待! 不占用cpu资源!使用notify()唤醒
    *
    */
    public class MyThread implements Runnable {
    // 重写Thread中的run()方法! 是普通的方法!
    @Override
    public void run() {
    try {
    System.out.println("线程的运行状态");
    System.out.println("线程的阻塞状态");
    Thread.sleep(3000);
    for (int i = 1; i <= 10; i++) {
    System.out.println(Thread.currentThread().getName() + "====>"
    + i);
    }
    } catch (InterruptedException e) {
    System.out.println("线程异常死亡");
    }
    System.out.println("线程正常死亡");
    }

    public static void main(String[] args) {
    MyThread thread = new MyThread();
    Thread thread1 = new Thread(thread);
    System.out.println("线程的新生状态");
    thread1.start();
    System.out.println("线程的就绪状态");

    }

    }

     六、InterruptedException相关知识

    转载:http://blog.csdn.net/derekjiang/article/details/4845757

    当一个方法后面声明可能会抛出InterruptedException 异常时,说明该方法是可能会花一点时间,但是可以取消的方法。

    抛InterruptedException的代表方法有:

    1. Java.lang.Object 类的 wait 方法

    2. java.lang.Thread 类的 sleep 方法

    3. java.lang.Thread 类的 join 方法

    -- 需要花点时间的方法

    执行wait方法的线程,会进入等待区等待被notify/notify All。在等待期间,线程不会活动。

    执行sleep方法的线程,会暂停执行参数内所设置的时间。

    执行join方法的线程,会等待到指定的线程结束为止。

    因此,上面的方法都是需要花点时间的方法。

    -- 可以取消的方法

    因为需要花时间的操作会降低程序的响应性,所以可能会取消/中途放弃执行这个方法。

    这里主要是通过interrupt方法来取消。

    1. sleep方法与interrupt方法

    interrupt方法是Thread类的实例方法,在执行的时候并不需要获取Thread实例的锁定,任何线程在任何时刻,都可以通过线程实例来调用其他线程的interrupt方法。

    当在sleep中的线程被调用interrupt方法时,就会放弃暂停的状态,并抛出InterruptedException异常,这样一来,线程的控制权就交给了捕捉这个异常的catch块了。

    2. wait方法和interrupt方法

    当线程调用wait方法后,线程在进入等待区时,会把锁定接触。当对wait中的线程调用interrupt方法时,会先重新获取锁定,再抛出InterruptedException异常,获取锁定之前,无法抛出InterruptedException异常。

    3. join方法和interrupt方法

    当线程以join方法等待其他线程结束时,一样可以使用interrupt方法取消。因为join方法不需要获取锁定,故而与sleep一样,会马上跳到catch程序块

    -- interrupt方法干了什么?

    interrupt方法其实只是改变了中断状态而已。

    而sleep、wait和join这些方法的内部会不断的检查中断状态的值,从而自己抛出InterruptEdException。

    所以,如果在线程进行其他处理时,调用了它的interrupt方法,线程也不会抛出InterruptedException的,只有当线程走到了sleep, wait, join这些方法的时候,才会抛出InterruptedException。若是没有调用sleep, wait, join这些方法,或者没有在线程里自己检查中断状态,自己抛出InterruptedException,那InterruptedException是不会抛出来的。

    isInterrupted方法,可以用来检查中断状态

    Thread.interrupted方法,可以用来检查并清除中断状态。

    七、sleep 和 wait 的区别

    转载:http://blog.csdn.net/liuzhenwen/article/details/4202967

    第一种解释:

    功能差不多,都用来进行线程控制,他们最大本质的区别是:sleep()不释放同步锁,wait()释放同步缩.   
        
      还有用法的上的不同是:sleep(milliseconds)可以用时间指定来使他自动醒过来,如果时间不到你只能调用interreput()来强行打断;wait()可以用notify()直接唤起.

    第二种解释:

    sleep是Thread类的静态方法。sleep的作用是让线程休眠制定的时间,在时间到达时恢复,也就是说sleep将在接到时间到达事件事恢复线程执行,例如:
    try{
    System.out.println("I'm going to bed");
    Thread.sleep(1000);
    System.out.println("I wake up");
    }
    catch(IntrruptedException e) {
    }
    wait是Object的方法,也就是说可以对任意一个对象调用wait方法,调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify方法才会重新激活调用者,例如:
    //Thread 1

    try{
    obj.wait();//suspend thread until obj.notify() is called
    }
    catch(InterrputedException e) {
    }

    第三种解释:

    这两者的施加者是有本质区别的. 
    sleep()是让某个线程暂停运行一段时间,其控制范围是由当前线程决定,也就是说,在线程里面决定.好比如说,我要做的事情是 "点火->烧水->煮面",而当我点完火之后我不立即烧水,我要休息一段时间再烧.对于运行的主动权是由我的流程来控制.

    而wait(),首先,这是由某个确定的对象来调用的,将这个对象理解成一个传话的人,当这个人在某个线程里面说"暂停!",也是 thisOBJ.wait(),这里的暂停是阻塞,还是"点火->烧水->煮饭",thisOBJ就好比一个监督我的人站在我旁边,本来该线 程应该执行1后执行2,再执行3,而在2处被那个对象喊暂停,那么我就会一直等在这里而不执行3,但正个流程并没有结束,我一直想去煮饭,但还没被允许, 直到那个对象在某个地方说"通知暂停的线程启动!",也就是thisOBJ.notify()的时候,那么我就可以煮饭了,这个被暂停的线程就会从暂停处 继续执行.


    其实两者都可以让线程暂停一段时间,但是本质的区别是一个线程的运行状态控制,一个是线程之间的通讯的问题

     在Java.lang.Thread类中,提供了sleep(),
    而java.lang.Object类中提供了wait(), notify()和notifyAll()方法来操作线程
    sleep()可以将一个线程睡眠,参数可以指定一个时间。
    而wait()可以将一个线程挂起,直到超时或者该线程被唤醒。
        wait有两种形式wait()和wait(milliseconds).
    sleep和wait的区别有:
      1,这两个方法来自不同的类分别是Thread和Object
      2,最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
      3,wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在
        任何地方使用
       synchronized(x){
          x.notify()
         //或者wait()
       }
       4,sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

    *******************************************************************
    线程调度的方法:
    *******************************************************************
    八、线程的调度---Priority
     
    老师代码:

    package cn.bdqn.priority04;

    /**
    * 线程的调度:
    * 按照我们指定的规则,给多个线程分配cpu的资源!
    *
    线程的优先级
    从 1-10 默认是5
    优先级越高代表 获得cpu资源的概率越大! 概率大并不能代表一定能获取资源!
    有可能概率小的总是拿到资源!
    */
    public class MyThread implements Runnable {
    // 重写Thread中的run()方法! 是普通的方法!
    @Override
    public void run() {
    for (int i = 1; i <= 10; i++) {
    System.out.println(Thread.currentThread().getName() + "====>" + i);
    }
    }

    public static void main(String[] args) {
    Thread thread1 = new Thread(new MyThread(), "线程1");
    Thread thread2 = new Thread(new MyThread(), "线程2");
    System.out.println("thread1默认的优先级:" + thread1.getPriority());
    System.out.println("thread2默认的优先级:" + thread2.getPriority());
    thread1.setPriority(Thread.MAX_PRIORITY); // 优先级最高
    thread2.setPriority(Thread.MIN_PRIORITY); // 优先级最低
    System.out.println("************************");
    System.out.println("thread1修改后的优先级:" + thread1.getPriority());
    System.out.println("thread2修改后的优先级:" + thread2.getPriority());
    // 启动线程
    thread1.start();
    thread2.start();
    }

    }

     
    九、线程的调度--join
    老师代码:

    package cn.bdqn.join05;

    /**
    * 线程的调度:
    * 按照我们指定的规则,给多个线程分配cpu的资源!
    *
    * join:等待该线程执行完毕!
    */
    public class MyThread implements Runnable {

    @Override
    public void run() {
    for (int i = 1; i <= 100; i++) {
    System.out.println(Thread.currentThread().getName() + "====>" + i);
    }
    }

    // 主线程main
    public static void main(String[] args) throws InterruptedException {
    Thread thread1 = new Thread(new MyThread(), "线程1");
    thread1.start();
    // 当前是2个线程
    for (int j = 1; j <= 50; j++) {
    if (j == 10) { // 当主线程中的i为10的时候,我让thread1强行执行
    thread1.join(); // 主线程必须等待thread1执行完毕 才能继续执行
    }
    System.out.println(Thread.currentThread().getName() + "====>" + j);
    }
    }

    }

     
    十、线程的调度---yield
    老师代码:

    package cn.bdqn.yield06;

    /**
    * 线程的调度:
    * 按照我们指定的规则,给多个线程分配cpu的资源!
    *
    * yield: 线程之间的礼让,还是概率问题!
    * 可能我让你了,你不接受!
    */
    public class MyThread implements Runnable {
    @Override
    public void run() {
    for (int i = 1; i <= 50; i++) {
    System.out.println(Thread.currentThread().getName() + "====>" + i);
    if (i % 2 == 0) {
    System.out.println("线程礼让");
    Thread.yield();
    }
    }
    }

    // 主线程main
    public static void main(String[] args) throws InterruptedException {
    Thread thread1 = new Thread(new MyThread(), "线程1");
    Thread thread2 = new Thread(new MyThread(), "线程2");
    thread1.start();
    thread2.start();
    }

    }

     
    十 一、作业
     
    1、老师临近下课留下的练习题目(爬山)
     
    2、视频U1的全部看完 !!! ORZ
     
    3、多敲代码!多敲代码!多敲代码!
     
    4、做题
     
    十二、老师辛苦了!
     
     
  • 相关阅读:
    苹果 macOS 安装 Source Code Pro
    C# 中代码执行 ping 操作
    WPF 中 Path 使用虚线
    查看 Java Web 开发环境软件是 32 位还是 64 位
    linux 磁盘io监控
    Linux下系统如何监控服务器硬件、操作系统、应用服务和业务
    ORA-00257: archiver error. Connect internal only, until freed 错误的处理方法
    完全卸载oracle11g步骤
    用JDBC连接SQL Server2017数据库
    oracle INS-13001 环境不满足最低要求
  • 原文地址:https://www.cnblogs.com/wsnedved2017/p/6708597.html
Copyright © 2020-2023  润新知