• 一.线程概述


    1.进程和线程的概念

    进程:进程是操作系统结构的基础;是一次程序的执行;是一个程序及其数据在处理机上顺序执行时所发生的活动;是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位;进程是受操作系统管理的基本运行单元。

    线程:可以理解成是在进程中独立运行的子任务;使用多线程也就是在使用异步。线程分为两种一种是用户线程,一种是守护线程;守护线程是一种特殊的线程,当进程中不存在非守护线程了,则守护线程自动销毁(垃圾回收线程),setDaemon(true)设置线程为守护线程。

    2.创建线程的方式

    • 继承Thread类
    package chapter1.create;
    
    public class MyThread extends Thread{
    	
    	@Override
    	public void run() {
    		super.run();
    		System.out.println("MyThread");
    	}
    
    }
    
    package chapter1.create;
    
    public class Run {
        
        public static void main(String[] args) {
            MyThread myThread = new MyThread();
            myThread.start();
            System.out.println("end!");
        }
    
    }

    运行结果如下:

    end!
    MyThread

    线程是一个子任务,CUP以不确定的方式,或者说是随机的时间来调用线程中的run方法,所以就会出现先打印end!,再打印MyThread了。

    • 实现Runnable接口
    package chapter1.create;
    
    public class MyRunnable implements Runnable{
    
    	@Override
    	public void run() {
    		System.out.println("运行中...");
    	}
    
    }
    
    package chapter1.create;
    
    public class Run {
    	
    	public static void main(String[] args) {
    		MyRunnable myRunnable = new MyRunnable();
    		Thread thread = new Thread(myRunnable);
    		thread.start();
    		System.out.println("运行结束");
    	}
    
    }
    

     运行结果:

    运行结束
    运行中...
    Thread.java类也实现了Runnable接口,也就意味着Thread(myRunnable)可以传入一个Thread类的对象,这样做可以将一个Thread对象中的run方法交由其他的线程进行调用。

    使用继承Thread类的方式创建线程时,最大的局限就是不支持多继承。

    3.常用方法介绍

    • currentThread()方法可返回代码段正在被哪个线程调用的信息。
    package chapter1.create;
    
    public class MehthodCurrentThreadTest {
       
        static class CountOperate extends Thread{
            public CountOperate() {
                System.out.println("CountOperate init----begin");
                System.out.println("Thread.currentThread().getName()="+Thread.currentThread().getName());
                System.out.println("this.getName()="+this.getName());
                System.out.println("CountOperate init----end");
            }
            
            @Override
            public void run() {
                super.run();
                System.out.println("run----begin");
                System.out.println("Thread.currentThread().getName()="+Thread.currentThread().getName());
                System.out.println("this.getName()="+this.getName());
                System.out.println("run----end");
            }
        }
        
        public static void main(String[] args) {
            CountOperate countOperate = new CountOperate();
            Thread t = new Thread(countOperate);
            t.setName("A");
            t.start();
        }
    }

    运行结果:

    CountOperate init----begin
    Thread.currentThread().getName()=main
    this.getName()=Thread-0
    CountOperate init----end
    run----begin
    Thread.currentThread().getName()=A
    this.getName()=Thread-0
    run----end

    • isAlive()判断当前的线程是否处于活动状态,活动状态就是线程已经启动且尚未终止。
    • sleep()是在指定的毫秒数内让当前"正在执行的线程"休眠(暂停执行),这个"正在执行的线程"是指this.currentThread()返回的线程。
    • getId()取得线程的唯一标识。
    • yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上有获得CPU时间片。
    • suspend():暂停,已废弃。会有独占和不同步的问题。
    • resume():恢复,已废弃;会有独占和不同步的问题。

     4.停止线程

    判断线程是否为中断状态的方法:

    • interrupted():当前线程是否已经是中断状态,当前线程指运行interrupted()方法的线程,执行后具有将状态标志清除为false的功能;
      • public static boolean interrupted() {
              return currentThread().isInterrupted(true);
        }
    • isInterrupted():线程对象是否已经是中断状态,但不清除状态标志。

    停止线程的方法:

    • 使用interrupt方法中断线程,但方法并没有停止线程,只是将状态标志为中断,调用isInterrupted()将返回true。
    package chapter1.create.threadinterrupt;
    
    public class MyThread extends Thread{
    	
    	@Override
    	public void run() {
    		super.run();
    		for(int i=0;i<500000;i++) {
    			System.out.println("i="+(i+1)+"interrupted------------"+this.isInterrupted());
    		}
    	}
    
    }
    
    package chapter1.create.threadinterrupt;
    
    public class Run {
    	
    	public static void main(String[] args) {
    		try {
    			MyThread myThread = new MyThread();
    			myThread.start();
    			Thread.sleep(2000);
    			myThread.interrupt();
    		} catch (Exception e) {
    			System.out.println("main catch.");
    			e.printStackTrace();
    		}
    	}
    
    }
    

     运行结果:

    i=499992interrupted------------true
    i=499993interrupted------------true
    i=499994interrupted------------true
    i=499995interrupted------------true
    i=499996interrupted------------true
    i=499997interrupted------------true
    i=499998interrupted------------true
    i=499999interrupted------------true
    i=500000interrupted------------true

    在沉睡中停止:

    package chapter1.create.threadinterrupt;
    
    public class StopWhenSleepTest {
    
    static class MyThread extends Thread{
    		
    		@Override
    		public void run() {
    			super.run();
    			try {
    				System.out.println("run begin");
    				Thread.sleep(200000);
    				System.out.println("run end");
    			} catch (InterruptedException e) {
    				System.out.println("进MyThread.java类run方法中的catch了。"+this.isInterrupted());
    				e.printStackTrace();
    			}
    		}
    	}
    	
    	public static void main(String[] args) {
    		try {
    			MyThread myThread = new MyThread();
    			myThread.start();
    			Thread.sleep(2000);
    			myThread.interrupt();
    		} catch (Exception e) {
    			System.out.println("main catch.");
    			e.printStackTrace();
    		}
    		System.out.println("Main end");
    	}
    }
    

     运行结果:

    run begin
    Main end
    进MyThread.java类run方法中的catch了。false
    java.lang.InterruptedException: sleep interrupted
        at java.lang.Thread.sleep(Native Method)
        at chapter1.create.threadinterrupt.StopWhenSleepTest$MyThread.run(StopWhenSleepTest.java:12)

    如果在sleep状态下停止线程,会进入catch,并且清楚停止状态值,使之成为false。先interrupt再sleep也会进入catch,此处不做赘述。

    • 异常法
    package chapter1.create.threadinterrupt;
    
    public class StopThreadByExceptionTest {
    	
    	static class MyThread extends Thread{
    		
    		@Override
    		public void run() {
    			super.run();
    			try {
    				for(int i=0;i<500000;i++) {
    					if(this.isInterrupted()) {
    						System.out.println("已经是停止状态了!我要退出了");
    						throw new InterruptedException();
    					}
    					System.out.println("i="+(i+1));
    				}
    			} catch (InterruptedException e) {
    				System.out.println("进MyThread.java类run方法中的catch了。");
    				e.printStackTrace();
    			}
    		}
    	}
    	
    	public static void main(String[] args) {
    		try {
    			MyThread myThread = new MyThread();
    			myThread.start();
    			Thread.sleep(2000);
    			myThread.interrupt();
    		} catch (Exception e) {
    			System.out.println("main catch.");
    			e.printStackTrace();
    		}
    	}
    
    }
    

     运行结果:
    i=420003
    i=420004
    i=420005
    i=420006
    i=420007
    i=420008
    i=420009
    i=420010
    i=420011
    已经是停止状态了!我要退出了
    进MyThread.java类run方法中的catch了。
    java.lang.InterruptedException
        at chapter1.create.threadinterrupt.StopThreadByExceptionTest$MyThread.run(StopThreadByExceptionTest.java:14)

    • 使用return停止线程:判断this.isInterrupted()为true,return。不过还是建议使用“异常法”,因为在catch块中可以对异常的信息进行相关的处理,而且使用异常流能更好、更方便地控制程序的运行流程。
    • stop()暴力停止。该方法已经被废弃,因为如果强制让线程停止则有可能使一些清理性的工作得不到完成。另外一个情况就是对锁定的对象“解锁”,导致数据得不到同步的处理,出现数据不一致的问题。

     5.线程的优先级

    setPriority(int priority):值的范围1-10,设置线程优先级有助于帮“线程规划器”确定在下一次选择哪一个线程来优先执行。

    • 线程的优先级具有继承性,比如A线程启动B线程,则B线程的优先级与A是一样的。
    • 线程的优先级具有一定的规则性,也就是CPU尽量将执行资源让个优先级较高的线程。
    • 线程的优先级具有随机性,也就是优先级较高的线程不一定每一次都先执行。
  • 相关阅读:
    机器学习笔记1
    Matlab学习日记之基础知识
    Matlab学习日记之操作界面
    Matlab学习日记之绘图
    Matlab学习日记之数学应用
    Matlab学习日记之映像
    机器学习笔记4
    机器学习笔记2
    在线CHM阅读器(2)——文件提取及关键文件解析
    一步一步打造WebIM(1)
  • 原文地址:https://www.cnblogs.com/hunter-56213/p/11044756.html
Copyright © 2020-2023  润新知