• java多线程(1) 线程的基本概念


    一、线程的基本概念:                        

    线程是一个程序里面不同的执行路径。
    程序里面不同的执行路径,每一个分支都是一个线程。
     
    进程:静态的概念。机器上的一个class文件,机器上的一个exe文件,这叫一个进程。
    机器里面实际上运行的都是线程。
    window等。linux等都是多进程,多线程的系统。
     
    CPU的执行是这样的:
    CPU速度比较快,一秒钟算好几亿次,它把自己的时间分成一个一个的小时间片,这个时间片我执行你一会,再执行他一会,虽然有几十个线程,
    没关系,执行这个一会,执行那个一会,挨着排的都执行一遍,但是对我们人来说,因为它速度太快了,你看起来就好像好多线程在同时执行一样。
    但实际上,在一个时间点上, 这个CPU只有一个线程在运行。
    如果机器是双CPU,或者是双核,那么确实是多线程。
     
    二、线程的启动和创建:                                
     
    例子1:实现Runnable接口:
    package com.cy.thread;
    
    public class TestThread1 {
        public static void main(String[] args) {
            Runner1 r = new Runner1();
            Thread t = new Thread(r);
            
            //启动一个线程,线程启动必须调用Thread类的start()方法
            //start方法会通知cpu,我现在有个新线程了啊,已经准备好了,您老人家什么时候有时间赶紧给我点时间片。
            t.start();
            
            for(int i=0; i<100; i++){
                System.out.println("Main Thread:----- " + i);
            }
        }
    }
    
    /**
     * 实现了Runnable之后,jdk就知道了,这是一个线程类。
     */
    class Runner1 implements Runnable{
    
        @Override
        public void run() {
            for(int i=0; i<100; i++){
                System.out.println("Runner1: " + i);
            }
        }
        
    }

    console:

     
     例子2:继承Thread类:
    package com.cy.thread;
    
    public class TestThread1 {
        public static void main(String[] args) {
            Runner1 r = new Runner1();
            r.start();
            
            for(int i=0; i<100; i++){
                System.out.println("Main Thread:----- " + i);
            }
        }
    }
    
    
    class Runner1 extends Thread{
    
        @Override
        public void run() {
            for(int i=0; i<100; i++){
                System.out.println("Runner1: " + i);
            }
        }
        
    }
    三、线程的状态转换:                                            
     
     
    new Thread()一个线程之后,不会马上执行而是进入就绪状态,因为cpu很忙,可能正在执行其他程序;
    等到cpu有空了,cpu分配时间片执行(调度)这个Thread一会;Thread进入运行状态;
    当cpu分配给这个Thread的时间片用完了,或者其他原因故障等,Thread不再执行,阻塞,再次进入就绪状态;
    直到这个Thread的程序执行完毕;终止。
     
    四、线程控制的基本方法:                                          
    isAlive():            判断线程是否还活着,即线程是否还未终止;就绪、运行、阻塞叫活着。终止了就死了。线程创建完还没启动那也是死的。
    getPriority()        获得线程的优先级数值;优先级越高的线程获得的cpu执行的时间越多。
    setPriority()        设置线程的优先级数值;
    Thread.sleep()        将当前线程睡眠指定毫秒数。
    join()            合并某个线程。
    yield()            高风亮节,让出cpu,让其他的线程执行,而自己进入就绪状态。
    wait()            当前线程进入对象的wait pool;
    notify、notifyAll()    唤醒对象的wait pool中的一个/所有等待线程。
    View Code

    五、sleep方法:                                                

    package com.cy.thread;
    
    import java.util.Date;
    
    public class TestInterrupt {
        public static void main(String[] args) {
            MyThread thread = new MyThread();
            thread.start();
            try {
                /**
                 * 在哪个线程里面调用sleep方法,就让哪个线程睡眠。
                 */
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            /**
             * interrupt()方法:thread线程在睡眠的时候,将它打断。
             * 这里为了例子演示,让子线程结束。
             * 但这不是让子线程结束的最好方法。
             */
            thread.interrupt();
        }
    }
    
    class MyThread extends Thread{
    
        @Override
        public void run() {
            while(true){
                System.out.println("==="+new Date()+"===");
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    return;
                }
            }
            
        }
    }
    View Code

    console打印:

     上面的程序提供一个结束Mythread线程的方法:
    /**
     * 提供一个让线程结束的方法:
     * thread.flag = false;   run()方法就不再执行了,run方法一结束,线程就结束了。
     */
    class MyThread2 extends Thread{
        
        boolean flag = true;
        
        @Override
        public void run() {
            while(flag){
                System.out.println("==="+new Date()+"===");
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    return;
                }
            }
            
        }
    }
    View Code

    六、join方法:                                                      

    package com.cy.thread;
    
    public class TestJoin {
        public static void main(String[] args) {
            MyThread2 t1 = new MyThread2("t1");
            t1.start();
            try {
                /**
                 * 将t1线程合并到main线程,和main线程一块执行。
                 */
                t1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            for(int i=0; i<=5; i++){
                System.out.println("i am main thread");
            }
        }
    }
    
    class MyThread2 extends Thread{
        MyThread2(String s){
            super(s);
        }
        
        @Override
        public void run() {
            for(int i=0; i<=5; i++){
                System.out.println("i am " + getName());
                try{
                    sleep(1000);
                }catch(InterruptedException e){
                    return;
                }
            }
        }
        
    }
    View Code

     七、yield方法:                                                
    执行到某一个点的时候,让出CPU,其他的线程有机会执行,不要说老让我自己一个人占着;
    但是我就让一下,不是说从此我就不再执行了;
    package com.cy.thread;
    
    public class TestYield {
        public static void main(String[] args) {
            //可以使用同一个线程类,new两个线程。
            MyThread3 t1 = new MyThread3("t1");
            MyThread3 t2 = new MyThread3("t2");
            t1.start();
            t2.start();
        }
    }
    
    class MyThread3 extends Thread{
        MyThread3(String s){
            super(s);
        }
    
        @Override
        public void run() {
            for(int i=0; i<=100;i++){
                System.out.println(getName() + ": " +i);
                if(i%10 == 0){
                    yield();
                }
            }
        }    
    }
    View Code
    观察输出,可以看到,每当被10整除后,下一个输出的一定是另外一个线程的。
     
    八、线程的优先级:                                                
    Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。
    线程调度器按照线程的优先级决定应调度哪个线程来执行。
    线程的优先级用数字表示,范围从1-10,一个线程默认的优先级是5;
    Thread.MIN_PRIORITY = 1;
    Thread.MAX_PRIORITY = 10;
    Thread.NORM_PRIORITY = 5;
    使用下述方法获得或设置线程对象的优先级:
    int getPriority();
    void setPriority(int newPriority);
    package com.cy.thread;
    
    public class TestPriority {
        public static void main(String[] args) {
            Thread t1 = new Thread(new T1());
            Thread t2 = new Thread(new T2());
            t1.setPriority(Thread.NORM_PRIORITY + 3);
            t1.start();
            t2.start();
        }
    }
    
    class T1 implements Runnable{
    
        @Override
        public void run() {
            for(int i=0; i<1000; i++){
                System.out.println("T1: " + i);
            }
        }
    }
    
    class T2 implements Runnable{
    
        @Override
        public void run() {
            for(int i=0; i<1000; i++){
                System.out.println("----T2: " + i);
            }
        }
    }
    View Code
    可以看到,t1得到cpu执行的时间片多,开始打印的都是t1,少部分t2。等到t1执行完了,才开始都是t2.
     
     
     
     
     
    ---------------
  • 相关阅读:
    java 编程语言基础 第一章 自我介绍
    Spring详解(四)------注解配置IOC、DI
    Spring详解(三)------DI依赖注入
    Spring详解(一)------概述
    mybatis 详解(十一)------ mybatis和spring整合
    mybatis 详解(十)------ 逆向工程
    mybatis 详解(九)------ 一级缓存、二级缓存
    mybatis 详解(八)------ 懒加载
    mybatis 详解(七)------一对一、一对多、多对多
    06-单例模式
  • 原文地址:https://www.cnblogs.com/tenWood/p/7113189.html
Copyright © 2020-2023  润新知