内存:所有的应用程序都需要进入到内存中执行临时存储RAM
硬盘:永久存储ROM
点击一个应用程序的功能执行,就会开启一条应用程序到cpu的执行路径,cup就可以通过这个路径执行功能,这个路径有一个名字,叫线程。
线程属于进程:是进程中的一个执行单元,负责程序的执行
线程的好处:
如:单核心线程cpu
4核心8线程
分时调度
抢占式调度
主线程:执行主(main)方法的线程
单线程程序:Java程序中只有一个线程执行从main方法开始,从上到下依次执行
创建多线程程序的第一种方式:创建Thread的子类java.lang.Thread类:是描述线程的类,我们想要实现多线程程序,就必须继承Thread类。
实现步骤:
Java使用的就是抢占式调度。优先级高的线程使用cpu先使用,若相同,随机选择一个。
//1.创建一个Thread类的子类publicclassMyThreadextendsThread{//2.在Thread类的子类中重写Thread类的run方法,设置线程任务(开启线程要做什么?)@Overridepublicvoidrun(){for(inti=0;i<20;i++){System.out.println("run:"+1);}}}publicclassCaiNiao{publicstaticvoidmain(String[]args){//3创建Thread类的子类对象MyThreadmt=newMyThread();//4.调用Thread类中的方法start方法,开启新的线程,执行run方法。mt.start();//主线程会继续执行主方法中的代码for(inti=0;i<37;i++){System.out.println("main:"+i);}}}创建多线程程序的第二种方法:实现Runnable接口java.lang.Runnable
java.lang.Thread类的构造方法
实现Runnable接口创建多线程程序的好处:1避免了单继承的局限性
2增强了程序的扩展性,降低了程序的耦合性(解耦)
匿名内部类的作用:简化代码
格式:
new父类/接口(){重置父类/接口中的方法};//线程的父类是Thread//newMyThread().start();//线程的接口Runnable//Runnabler=RunnableTmpl();//多态//newRunnable(r).start();Thread类的常用方法获取线程的名称:
设置线程的名称:
创建三个的线程,同时开启,对共享的票进行出售
publicclassRunnableImplimplementscRunnable{//定义一个多线程共享的票源privateintticket=100;//设置线程任务:买票@Overridepublicvoidrun(){//使用死循环,让卖票操作重复执行while(true){//先判断票是否存在if(ticket>0){//提高安全问题出现的概率,让程序睡眠try{Thread.sleep(10);}catch(InterruptedExceptione){e.printStackTrace();}//票存在,卖票ticket--System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");ticket--;}}}}publicclassCaiNiao{publicstaticvoidmain(String[]args){//创建Runnable接口的实现类对象RunnableImplrun=newRunnableImpl();//创建Thread类对象,构造方法中传递Runnable接口的实现类对象Threadt0=newThread(run);Threadt1=newThread(run);Threadt2=newThread(run);//调用start方法开启多线程t0.start();t1.start();t2.start();}}这样会导致一个结果
格式:syncharonized(锁对象){可能会出现线程安全问题的代码(访问了共享数据的代码)}注意:
publicclassRunnableImplimplementscRunnable{//定义一个多线程共享的票源privateintticket=100;//设置线程任务:买票@Overridepublicvoidrun(){//使用死循环,让卖票操作重复执行while(true){//同步代码块syncharonized(obj){//先判断票是否存在if(ticket>0){//提高安全问题出现的概率,让程序睡眠try{Thread.sleep(10);}catch(InterruptedExceptione){e.printStackTrace();}//票存在,卖票ticket--System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");ticket--;}解决线程安全问题的二种方案:使用同步方法使用步骤:
格式:定义方法的格式
修饰符synchronized返回值类型方法名(参数列表){可能会出现线程安全问题的代码(访问了共享数据的代码)}解决线程安全问题的三种方案:使用Lock锁java.util.concurrent.Locks.Lock接口Lock实现提供了比使用synchronized方法和语句可获得的更广泛的锁定操作。
Lock接口中的方法:
publicstaticvoidsleep(Longmillis):使用当前正在执行的线程以指定的毫秒数暂停(暂停停止执行).
注意:
voidwait()
voidnotify()
概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同重点:有效的利用资源
1资源类:包子类
2生产者(包子铺)类:是一个线程类,可以继承Thread
true:有包子
false:没有包子
3消费者(吃货)类:是一个线程类,可以继承Thread
false:没有包子
true:有包子
4测试类:
线程池概念:其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多的资源。
线程池:容器-->集合(ArrayList,HashSet,LinkedList
Threadt=list.remove(0);返回的是被移除的元素,(线程只能被一个任务使用)Threadt=linked.removeFist();list.add(t);linked.addLast(t);在JDK1.5之后,JDK内置了线程池,我们可以直接使用合理利用线程池带来的好处:
线程池的代码实现:JDK1.5之后提供的
java.util.concurrent.Executors;线程池的工厂类,用来生成线程池Executors类中的静态方法:
staticExecutorServicenewFixedThreadPool(intnThreads)创建一个可重用的固定线程数的线程池参数:
intnTherad:创建线程池中包含的线程数量返回值:
ExecutorService接口,返回的是ExecutorService接口的实现类对象,我们可以使用ExecutorService接口接收(面向接口编程)java.util.concurrent.ExecutorService:线程池接口
submit(Runnabletask)提交一个Runnable任务用于执行关闭/销毁线程池的方法
voidshutdown()线程池的使用步骤:ExecutorServicees=Executors.newFixedThreadPool(2)es.submit(newRunnableImpl());//创建了一个新的线程执行Lambda表达式函数式编程思想概述---强调做什么,而不是以什么形式做
面向对象的思想:
函数式编程思想
publicclassCaiNiao{publicstaticvoidmain(String[]args){//匿名内部类,实现多线程//Runnabletask=newRunnable()Runnabletask=newRunnable(){@Overridepublicvoidrun(){//覆盖重写抽象方法System.out.println(Thread.currentThread().getName()+"新线程创建了");System.out.println("多线程任务执行!");}};newThread(task).start();//开启线程}}匿名内部类的好处与弊端
publicclassCaiNiao{publicstaticvoidmain(String[]args){//匿名内部类,实现多线程//Runnabletask=newRunnable()newThread(newRunnable(){@Overridepublicvoidrun(){//覆盖重写抽象方法System.out.println(Thread.currentThread().getName()+"新线程创建了");System.out.println("多线程任务执行!");}}).start();//开启线程}}Lambda写法()->{}
publicclassCaiNiao{publicstaticvoidmain(String[]args){//匿名内部类,实现多线程//Runnabletask=newRunnable()newThread(()->{//覆盖重写抽象方法System.out.println(Thread.currentThread().getName()+"新线程创建了");System.out.println("多线程任务执行!");}).start();//开启线程}}Lambda表达式的标准格式由三部分组成:
解释说明格式:
Lambda表达式:是可推导,可以省略
可以省略的内容:
注意:要省略{},return,分号必须一起省略
newThread(()->{//覆盖重写抽象方法System.out.println(Thread.currentThread().getName()+"新线程创建了");}).start();//开启线程newThread(()->System.out.println(Thread.currentThread().getName()+"新线程创建了")).start();//开启线程