zoukankan      html  css  js  c++  java
  • 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.
     
     
     
     
     
    ---------------
  • 相关阅读:
    记一道乘法&加法线段树(模版题)
    2021CCPC网络赛(重赛)题解
    Codeforces Round #747 (Div. 2)题解
    F. Mattress Run 题解
    Codeforces Round #744 (Div. 3) G题题解
    AtCoder Beginner Contest 220部分题(G,H)题解
    Educational Codeforces Round 114 (Rated for Div. 2)题解
    Codeforces Global Round 16题解
    Educational Codeforces Round 113 (Rated for Div. 2)题解
    AtCoder Beginner Contest 182 F
  • 原文地址:https://www.cnblogs.com/tenWood/p/7113189.html
Copyright © 2011-2022 走看看