初识多线程

1.认识多线程

线程
线程存在于进程的内部,是比进程还小的单为。进程是系统分配资源的最小单位,线程是系统调度的最小单位。一个进程之内的线程之间是可以共享资源的,每一个进程至少存在一个线程,即主线程。

多线程的作用
在确保安全的情况下,尽可能提高系统效率,尽可能利用系统资源。

使用场景
创建线程是比较耗费时间和资源的,所以要综合考虑同时执行指令(任务量)+创建线程数+系统可利用资源(内存,CPU)
一般在一个时间点要同时做多件事(执行多行代码)时就可以使用多线程。

内部类
匿名内部类:在一个方法中,new类型/接口(){ } ()指定构造方法,{ }指定要重写的方法
静态内部类:定义在另一个类的内部的类,作为另一类的静态成员,通过 类名.静态成员名 来访问。

public class 匿名内部类 {
    public static void main(String[] args) {
        A a = new A(){//匿名内部类,本质是A的子类,但不能等同A类型
            //可以重写方法,或不重写(继承)
            @Override
            public void pro() {
                System.out.println("pro");
            }
        };
        a.pro();//想打印pro

        B b = new B() {//匿名内部类:B接口的实现类,不能等同于B
            @Override
            public void pro() {
                System.out.println("pro");
            }
        };
        b.pro();//打印pro
    }

    //静态内部类
    static class A{
        public void pro(){
            System.out.println("a pro");
        };
    }
    //内部接口
    interface B{
        void pro();
    }
}

创建线程的方法

  1. 继承 Thread 类
    可以通过继承Tread来创建一个线程,该方法的好处是this代表的就是当前的线程,不需要Tread.currentTread()来获取当前进程的引用。
class MyThread extents Thread{
@Override
public void run(){
System.out.println("这是线程运行的代码")
}
}
MyThread t=new Mytraed();
t.start();线程开始运行
  1. 实现Runable接口
    通过实现Runnable接口,并且调用Tread 的构造方法时,将Runnable对象作为target参数传入来创建线程对象。该方法的好处是可以规避类的单继承的限制,但需要通过Thread.currentThread()来获取当前线程的引用
class MyRunnable implements Runnable{
@Override
	public void run(){
		System.out.println(Thread.currentThread().getName()+"这是线程运行的代码")
} 
}
Thread t=new Thread(new MyRunnable())
t.start();
  1. 其他变形
    使用匿名类创建Thread 子类对象
Thread t1=new Thread(){
	@Override
	public void run(){
		System.out.println("使用匿名内部类创建Tread的子类对象")}
};
	使用匿名类创建Runable子类对象
Thread t2=new Thread(new Runnable(){
	@Override
		public void run(){
			System.out.println("使用匿名类创建Runnable子类对象")}
});

Thread类及常见API

	Thread类是JVM用来管理线程的一个类,每一个线程都有唯一的Thread对象与之关联。

Thread类的构造方法

  1. Thread(),创建线程对象
  2. Thread(Runnable target),使用Runnable对象创建线程对象
  3. Thread(String name),创建线程并命名
  4. Thread(Runnable target,String name),使用Runnable对象创建线程,并命名

Thread的几个常见属性

  • 属性:ID,获取方法:getId()
  • 属性:名称,获取方法:getName()
  • 属性:状态,获取方法:getState()
  • 属性:优先级,获取方法:getPriority()
  • 属性:是否是后台线程,获取方法:isDamon()
  • 属性:是否存活,获取方法:isAlive()
  • 属性:是否被中断,获取方法:isInterrupted()

启动线程
start:线程启动的方法,启动之后才表现并发,并行的特性。
申请系统调度线程,让CPU执行(创建态——>就绪态),如果线程获取CPU时间片,就开始执行任务(Thread类中run方法和Runnable对象中run,就是任务的定义)

void start();//导致此线程执行,Java虚拟机调用此现成的run方法。

线程中断

  1. 通过共享的标记来进行沟通
public class ThreadDemo{
	private static class MyRunnable implements Runnable{
	public volatile boolean isQuit=false;
	@Override
	public void run(){
	while(!isQuit){
		System.out.println(Thread.currentThread().getName()+"正在执行线程")
		try{
	Threadsleep(1000);
	}catch(InterruptedException e){
		e.printStackTrace();
		}
	}
	System.out.println(Thread.currentThread().getName()+"收到消息,线程已经停止")
	}
	}
	public static void main(String[] args)throw InterruptedException{
	Mythread target=new Mythread();
	Thread thread=new Thread(target,"A")
	System.out.println(Thread.currentThread().getName()+"让A线程开始执行");
	thread.start();
	Thread.sleep(10*1000);
	System.out.println(Thread.currentThread().getName()+"让线程A停止执行"
	target.isQuit=true;
	}
}

当标志位 isQuit 置为true之后,线程Arun方法退出while循环,停止线程运行。

  1. 通过调用interrupt()方法来通知,初识值=false(没有被中断)
public class ThreadDemo{
	private static class MyRunnable implements Runnable{
	@Override
	public void run(){
	while(!Thread.interrupted()){
		System.out.println(Thread.currentThread().getName()+"正在执行线程")
		try{
	Threadsleep(1000);
	}catch(InterruptedException e){
		e.printStackTrace();
		}
	}
	System.out.println(Thread.currentThread().getName()+"收到消息,线程已经停止")
	}
	}
	public static void main(String[] args)throw InterruptedException{
	Mythread target=new Mythread();
	Thread thread=new Thread(target,"A")
	System.out.println(Thread.currentThread().getName()+"让A线程开始执行");
	thread.start();
	Thread.sleep(10*1000);
	System.out.println(Thread.currentThread().getName()+"让线程A停止执行"
	thread.interrupt();
	}
}

中断某个线程
(1)线程中断标志位=true
(2)线程要不要中断,线程定义的代码任务自行决定
(3)如果线程处于阻塞状态(调用多线程阻塞API方法,显示抛出InterruptException的方法),直接提前让线程从阻塞状态转变为就绪态,在系统调度执行后,以抛出异常的方式继续执行

线程等待
有时,我们需要等待一个进程完成工做后,才能进行自己的下一步工作。

API方法:
线程等待API(1)无参方法,就是线程执行完毕
(2)有参方法:是线程执行完毕和时间到达任意一个满足,满足等待时间后继续往下执行

线程让步
暂停当前线程对象(交出CPU权限,让CPU去执行其他的线程),并执行其他线程,但是不会让线程进入阻塞态,而是让线程返回就绪态

获取当前线程引用
获取当前线程的引用
线程状态

线程状态转换
Java中线程的状态

  • NEW
  • RUNNABLE(可运行态=就绪态+运行态)
  • BLOCKED
  • WAITING
  • TIMED_WAIT
  • TERMINATED

线程池

  1. 线程池的作用:不用每次执行任务时,都要创建进程(会真实创建系统级别的线程,线程的创建与销毁都很耗时,而是可以使用线程池中的线程来复用,减少每次启动、销毁线程的开销

  2. 线程池的重要参数
    (1)corePoolSize:核心线程数
    (2)maximumPoolSize:最大线程数
    (3)keepAliveTime:非核心线程的空闲时间,超过KeepAliveTime就会自动被回收
    (4)TimeUnit:空闲时间KeepAliveTime的时间单位
    (5)workQueue:用于保存任务的队列,可以为有界、无界同步队列
    (6)ThreadFactory:创建线程的工厂类,默认使用Excutors.defaultThreadFactory()
    (7)RejectedExcutionHandler(拒绝策略):线程池已经满了(保存任务的队列已满),不能再接收任务时采取拒绝策略处理。

  3. 常用线程池创建
    1、自动创建

  • newCachedThreadPool:初始化一个缓存线程池,不会对线程的数量做出限制,最大线程数完全依赖于操作系统

  • newFixedThreadPool:初始化一个指定数量的线程池,corePoolSize==maxiPoolSize,使用LinkedBlockingQueue作为阻塞队列

  • newSingleThreadExecutor:初始化只有一个线程

  • newScheduledThreadPool:创建一个定时调度的线程池,内置延迟队列,

     2、手动创建
    
ExecutorService pool = new ThreadPoolExecutor
(传入各参数的的值(核心线程数、最大线程数等));
  1. 停止线程池
    (1)shutDown():中断队列中的任务,工作线程正在执行的任务还是执行,等执行完毕才关闭线程
    (2)shutDownNow():中断队列中的任务,及工作线程正在执行任务,然后关闭线程池。

线程池执行流程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值