`

Java笔记-Java基础(多线程)

    博客分类:
  • java
 
阅读更多

Java基础-多线程

 

1.线程:程序中单独顺序的控制流。线程本身不能运行,只能用于程序中。

进程:执行中的程序,

word,编辑的同时,可以打印,拼写检查

 

2.进程与线程的区别:

1)进程是静态的概念,线程是动态的概念 

2)多个进程的内部数据和状态是完全独立的;多线程是共享一块内存空间和一组系统资源,有可能相互影响

3)线程本身的数据通常只有寄存器数据,以及一个程序执行时使用的堆栈,

线程的切换比进程切换的负担要小

4)进程重量级的任务,需要分配给他们独立的地址空间,进程间通信是昂贵和受限的,进程间的转换也是需要花费的

线程是轻量的,共享相同的地址空间,并分享同一进程,通信便宜的,转换低成本的

 

3.多线程编程的目的:

最大限度的利用CPU资源

当某一线程的处理不需要占用cpu资源而只和IO等资源打交道时,让需要占用cpu资源的其他线程有机会获得cpu资源

  

*当程序运行时,就会自动的产生一个线程,main方法就运行在这个主线程内

*一个进程可以包含一个或多个线程

*一个程序实现多个代码同时交替运行就需要产生多个线程

*cpu随机的抽出时间,让我们的程序一会做这件事情,一会做另外一件事情

*java内置支持

*并发运行

*每个线程有独立的执行路径,多线程是多任务处理的一种特殊形式

*一个进程至少要包含一个线程

*对于单核cpu来说,某一时刻只能有一个线程在执行(微观串行),宏观来看,多个线程在同时执行(宏观并行)

*对于多核cpu来说,可以真正做到微观并行

 

4.多进程和多线程:

*多任务处理两种类型:

基于进程的,基于线程的

1)基于进程的多任务处理,程序是调度程序所分派的最小代码单位

2)基于线程的多任务处理,线程是最小的执行单位

意味着一个程序可以同时执行两个或多个任务的功能

word,编辑的同时,可以打印,拼写检查

 

5.如何实现:

5.1继承Thread类,重写run方法

将我们希望线程执行的代码放到run方法中,然后通过start方法启动线程

start方法首先为线程的执行准备系统资源,然后调用run方法


*如果直接调用run方法,将不是以单独线程的方式启动

*要想以多线程方式启动,必须调用start方法

*线程执行结束,不能restart

 

5.2实现Runnable接口,实现run方法

将我们希望线程执行的代码放到run方法中,

然后使用我们实现的类作为参数实例化一个Thread对象,通过这个Thread对象的start方法启动线程

 

*Thread类实现了Runnable接口

*当生成一个线程对象时,如果没有为其设定名字,那么线程名字将是如下形式:Thread-number
该number是自动增加的,并被所有的Thread对象所共享 

 

5.3线程的启动start方法

两种方法都要调用线程的start方法为线程分配必须的资源

 

当一个类已经继承了其他的非线程类的时候,如果要想使其成为线程类,则必须实现Runnable接口 

 

5.4线程的停止

线程的消亡不能通过stop方法,而是让run方法自然结束

推荐的方式:

 


 

6.线程的生命周期

创建、可运行、不可运行,消亡

 

6.1状态转换图

 

创建(new)、可运行(start)、运行、阻塞(sleep)、消亡 

 

7.优先级

便于调度

1)线程创建时,子继承父的优先级

2)线程创建后,可通过调用setPriority()方法改变优先级

3)1-10的正整数

7.1线程调度策略

1)选择优先级最高的线程运行,发生以下情况,会终止线程的执行

*线程体调用了yield方法,让出对cpu的占用

*调用了sleep方法,使线程进入睡眠状态

*线程由于IO操作而受到阻塞

*另一个更高优先级的线程出现

*在支持时间片的系统中,线程的时间片用完

 

8.关于成员变量与局部变量

多个线程对同一个对象的成员变量进行操作时,他们对成员变量是彼此影响的

一个线程对局部变量的改变对另一个线程不具有影响

 

9.线程的同步

多个线程同时访问一个有限的资源

解决方法:为资源加锁 

访问资源的第一个线程为其加上锁以后,其他线程便不能再使用那个资源,除非被解锁。

上锁是对对象上锁

 

9.1synchronized

修饰方法,修饰static方法,修饰代码块[synchronized(this)]

1)同步方法:synchronized修饰的方法

synchronized修饰的代码块

粗粒度

 

*java中的每个对象都有一个锁(或监视器),当访问某个对象的sychronized方法时,表示对该对象上锁

此时其他线程无法再访问该方法,直到执行完毕

*如果一个对象有多个synchronized方法,同一时刻某个线程已经进入到了某个synchronized方法,

那么在该方法没有执行完毕前,其他线程是无法访问该对象的任何synchronized方法的

*静态同步方法。如果某个synchronized方法是静态的,那么当线程访问该方法时,

它的锁并不是synchronized方法所在的对象,而是synchronized方法所在对象所对应的Class对象。

因此,当线程分别访问同一个类的两个对象的两个static,sychronized方法时,他们的执行顺序也是顺序的。

 

2)同步代码块

synchronized(obj),synchronized(this)

更细粒度

 

*当synchronized方法执行完或发生异常时,会自动释放锁

*被synchronized保护的数据应该是private的

*同步线程状态转换图

 

9.2线程间的相互作用

1)wait and notifiy,notifyAll

lock pool

wait pool

 

具有wait,notify的线程状态图

 

wait与notify方法都是定义在Object类中,而且是final的,因此会被所有Java类所继承,并且无法重写

这两个方法要求在调用时线程应该已经获得了对象的锁,因此对这两个方法的调用需要放在synchronized方法或块当中。

当线程调用了wait方法时,会释放掉对象的锁

当另外的线程调用了notify,notifyAll方法时,会唤醒处于wait状态状态的线程

 

生产者,消费者

哲学家就餐问题

死锁

 

*wait必须在synchronized代码块中调用,调用wait方法后会释放锁

另外线程调用notify或notifyAll方法会唤醒wait的线程,等到再次获得锁的时候恢复运行

*使用while进行条件 和 使用if进行条件判断比较

 

2)sleep也是会导致线程暂停的方法

定义在Thread类中

 

*sleep方法会导致线程睡眠指定的毫秒数

线程在睡眠的过程中是不会释放掉对象的锁的

 

*调用wait方法后,如果不调用nofity,notifyAll,将永远不会被唤醒

sleep在睡眠指定时间后,会自动醒来

以上两点是sleep和wait的区别

 

10.线程组

所有线程都隶属于一个线程组。可以是一个默认的线程组,也可以是一个创建线程时明确指定的组。

 

*在创建之初,线程被限制在一个组里,而且不可能改变到一个不同的组

*若创建多个线程而不指定一个组,他们会与创建它的线程属于同一个组

 

 

 

 

 

 

  • 大小: 476.6 KB
  • 大小: 298.2 KB
  • 大小: 296.7 KB
  • 大小: 323.3 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics