正在加载……
专注、离线、切勿分心
Thread 引入:
█ 单线程程序
     ☞如果程序只有一条执行路径
█ 多线程程序
     ☞如果程序有多条执行路径   

什么是多线程:
█ 进程
    ☞是操作系统进行资源分配和调度的基本单位
█ 线程
    ☞是程序使用cpu的基本单位
    ☞是进程中单个顺序控制流(执行路径),是一条单独执行的路径。单线程,多线程
█ 举例
    ☞扫雷,迅雷下载

JAVA程序的运行原理:
█ Java命令会启动JVM,即启动了一个进程
    ☞该进程会启动一个主线程,然后主线程调用某个类的main方法,所以main方法都是运行在主线程里。(之前我们写的基本都是单线程程序  )

█ 思考 JVM是单线程还是多线程?    多线程,有一个线程是去执行main,还有一个垃圾回收线程,默默的进行不用内存回收;


实现方案:
(eclipse 中ctrl + t 可以查看类的层次结构)
方式一
继承Thread类
重写子类的run方法 
创建该子类的对象
启动线程

方式二
创建线程的另一种方法是声明实现 Runnable 接口的类
然后实现 run 方法。
然后可以分配该类的实例
在创建 Thread 时作为一个参数来传递并启动。



线程调度:
假设只有一个CPU(单核情况)
█ 线程两种调度模型
      ☞分时调度模型(平均分配)
      ☞抢占式调度模型(优先级)
Java使用哪种? 抢占式
线程优先级:
如何获取当前线程优先级?    //getPriority();
如何设置当前线程优先级?    //setPriority();
线程优先级范围?  1-10   1最低优先级   默认5


线程控制:
线程睡眠
static void sleep(long millis);
线程加入
public final void join();
线程礼让
public static void yield();
后台线程
public final void setDaemon(boolean on);
中断线程
public void interrupt();
public final void stop();



线程的生命周期:
新建
创建线程对象
就绪
有执行资格,等待cpu调度
运行
取得执行权,开始执行
阻塞: 无执行资格,无执行权
死亡
执行完毕,等待垃圾回收




//第一种实现方式
TestMain.java TestMain2.java
package com.java.thread;
public class TeseMain {
        public static void main(String[] args) {
                //3、创建对象
                MyThread thread1=new MyThread();
                thread1.setName("张三");  //这里默认名称是 Thread-0;后面0是索引号
                //4、启动该线程应该使用 start 方法,启动系统会调用线程里的run方法
                thread1.start(); //IllegalThreadStateException     //线程不能用一个对象调用重复启动,如果已经启动了,再次使用start重新启动,就会报这个异常
                //thread1.run();  //和普通的方法调用没有任何区别,不会启动子线程,而且不会将该方法放到子线程里执行
                MyThread thread2=new MyThread();
                thread2.setName("李四");
                thread2.setPriority(10);     //设置优先级,数字越大,优先级越高;1~10
                //不是cpu中设置的,cpu仅仅将我们的代码里设置的优先级作为参考
                thread2.start();
                for(int i=0;i<10;++i){
                        System.out.println(Thread.currentThread().getName()+" : "+i);  //获取当前线程,并输出他的名字
                }
        }
}
//1、继承 Thread 类
class MyThread extends Thread{  //方式一
//2、重写 run 方法
        public void run() {
                super.run();
                String name = getName();    //父类方法,返回调用方法的对象名
                int p=getPriority();    //获取当前线程优先级
                for(int i=0;i<10;++i){
                        System.out .println("MyThread.run() :"+name+":  "+i+"  优先级:"+p);
                        try {
                                Thread.sleep(500);   //静态方法,可以直接写;但是推荐类名去调用
                                //当线程sleep的时候,cpu就会将其挂起,执行其他线程;睡醒后等待cpu调用执行
                        }catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                //父类有setName方法,可以修改调用线程的名称;改完后getName到的就是刚设置好的
              }
        }
}
package com.java.thread;
public class TestMain2 {

        public static void main(String[] args) {
                MyThread2 t1=new MyThread2();
                t1.start();
                try{
                        t1.join();    //join方法,等待线程结束
                }catch(InterruptedException e){
                        e.printStackTrace();
                }
                for(int i=0;i<10;i++){
                        System.out .println("main thread() :"+i);
                }
        }
}
class MyThread2 extends Thread{
                public void run() {
                        super.run();
                        String name = getName();   
                        for(int i=0;i<10;++i){
                                System.out .println("MyThread2.run() :"+name+":  "+i);
                    }
            }
}

部分执行结果

部分结果,main最后执行


TestMain3.java TestMain4.java
package com.java.thread;
public class TestMain3 {
        public static void main(String[] args) {
                MyThread3 t1=new MyThread3();
                t1.start();

                MyThread3 t2=new MyThread3();
                t2.setDaemon(true);    //true 就是把这个进程设置为守护进程;就是后台进程;等所以线程都执行完了退出,守护线程也就退出了
                t2.start();
        }
}
class MyThread3 extends Thread{
        public void run() {
                super.run();
                int p=getPriority();
                String name = getName();   
                for(int i=0;i<10;++i){
                        System.out .println("MyThread3.run() :"+name+":  "+i+"优先级  "+p);
                        Thread.yield();   //放弃cpu让给别人;放弃执行完后进入就绪状态,此时cpu可以再次调度
            }
    }
}

这里实验看不出什么区别
package com.java.thread;
public class TestMain4 {
        public static void main(String[] args) {
                MyThread4 t1=new MyThread4();
                t1.start();

                MyThread4 t2=new MyThread4();
                t2.start();
        }
}
class MyThread4 extends Thread{
        public void run() {
                super.run();
                int p=getPriority();
                String name = getName();   
                for(int i=0;i<10;++i){
                        System.out .println("MyThread3.run() :"+name+":  "+i+"优先级  "+p);
                        if(5==i){
                                Thread.currentThread().interrupt();    //中断线程
                                //Thread.currentThread().stop();        //过时不用了,不安全
                        }
            }
    }
}

//线程中断后cpu会挑选其他线程来执行,当没有可挑选的线程的时候,刚才中断的线程又可以接着开始执行;这段代码是最后两个线程都把i加到10


//第二种实现方式
TestMain.java
package com.java.thread2;

public class TestMain {

        public static void main(String[] args) {
                MyThread run1=new MyThread();
                Thread t1=new Thread(run1);   // 这种初始化方式,thread会再启动之后,调用到runable接口里的run方法,将其放在一个新的线程里执行
                Thread t2=new Thread(run1);
                t1.setName("第一");
                t2.setName("第二");
                t1.start();
                t2.start();

                Cat cat=new Cat();
                Thread cat_thread=new Thread(cat);
                cat_thread.start();
        }
}
class MyThread implements Runnable{
        String BookName="java";
        public void run() {
                for(int i=0;i<10;i++){
                        System.out.println(Thread.currentThread().getName()+": "+i);
                        System.out.println("MyThread.run() : "+BookName);
                }
        }
}
class Animal{
        String name;
}
class Cat extends Animal implements Runnable{
        public void run() {
                for(int i=0;i<10;i++){
                        System.out.println(Thread.currentThread().getName()+"Cat catch mouse "+i);
                }
        }
}
//线程争夺cpu资源,交替执行;每一句语句都是这样

方式一 VS 方式二
方式一的缺陷: 如果某个类已经有父类,则无法再继承Thread类
方式二的优点: 解决了单继承的局限性;还有一个优点,便于多线程共享数据


两种实现方式的对比:
方法1:需要多个对象
方法2:只需要新建一个对象即可,放入三个不同线程;实现了数据和业务模型的分离











posted on 2018-06-14 10:12  正在加载……  阅读(352)  评论(0编辑  收藏  举报