多线程

一、提到多线程,就不得不理解以下几点:

1.程序,进程,线程这三者之间的关系?

 

简单来说,一程序可以调用多个进程,比如一个视频播放器程序,里面就存在两个进程:一个是播放视频的进程,一个是下载上传视频的进程。

一个进程又同时调用多个线程,这个线程是隐藏的,用进程管理器看不到,可用其它的进程管理软件来查看。

三者的逻辑关系是程序调用进程,进程调用线程,一般来说程序下面都是多进程,不同的进程分工不同;进程下面也基本上是多线程的。

可以这样下定义:进程是系统进行资源分配和调用的独立单位,每一个进程,都由它自己的内存空间和系统资源

线程是进程的执行单元,执行路径,线程也是程序使用CPU的最基本单位

2.单线程与多线程以及多线程的意义?

如果程序只有一条执行路径,这就是单线程;相反如果程序有多条路径,那么就是多线程

看下面这段程序:

public class Thread {

public static void main(String[]args) {

//code..........

............

...........

}

}

这里面至少存在两条程序,一条是主线程main,另外一条就是垃圾回收线程,即JVM一遍"执行"main,"一边"也在执行垃圾回收机制

所以说java支持多线程,而多线程的意义它可以让程序在一个时间段执行多个事情,提高了应用程序的使用率;

比如上面那个例子,如果是单线程,那么JVM不得不执行一会main线程然后停下来去执行垃圾回收机制

3.理解并发与并行

思考:我们在一边玩游戏,一边带上耳机听歌,请问玩游戏与听歌是同时进行的吗?

显然不是,因为CPU在某一个时间点上只能做一件事,我们玩游戏,CPU就切换到执行游戏进程,听歌,CPU就切换到听歌进程;CPU就这样反复做这高效率的切换动作,这种切换是随机的,但是让我们人感觉到就是同时发生的,这就是并发的概念

并发:通过CPU调度算法,让用户看上去同时执行,实际上,是通过CPU在高速切换,并不是真正的额同时

并行:多个CPU实例或者多台机器同时执行一段处理逻辑,这就是真正的同时;

二,如何创建线程?

了解了多线程的意义所在,我们在处理一些问题上,就可以创建多条线程,充分使用CPU

Thread,这是JAVA为我们提供的唯一的线程类

通过查询API文档可知Thread类为我们提供了很多处理线程是需要的方法

这里先提两个:run()方法,与start()方法,run()方法里面存放着Thread线程对象需要执行的代码;调用start()方法,让所创建的线程处于就绪状态

创建线程的方式一:

1.类去继承(extends)Thread 类

2.该类重写Thread类的run方法,并且将线程要执行的代码,存放到run方法中

3.线程对象调用start方法,开启线程,线程会自动执行run方法

代码实例如下:

class Demo extends Thread {

String name;

Demo(String name) {

this.name = name;

}

//这一步很关键,重写run方法,这里面是线程所要执行的

public void run() {

for(int i=1;i<30;i++) { //利用currentThread()方法来获取当前正在执行的线程的名称

System.out.println(Thread.currentThread().getName()+"::"+this.name);

}

}

}

publicclass ThreadDemo {

public static void main(String[]args) {

Demo d1 = new Demo("1111");//创建线程对象

Demo d2 = new Demo("2222");

d1.start();//开启线程,执行run方法;但是注意,此时只是具备执行资格,CPU的执行是随机的

d2.start();

}

}

创建线程的方式二:

1.存放线程执行代码的类去实现(implements) Runnable接口

2.重写所实现接口的run方法,并将线程执行代码存放在run方法中

3.创建Thread对象,也就是创建线程

4.Thread线程对象调用start方法,启动线程

class Demo implements Runnable {

String name;

public void run() {

for(int i=0;i<30;i++) {

System.out.println(Thread.currentThread().getName()+"::"+);

}

}

}

public class TheadTest {

public void static main(String[]args) {

Demo d1= new Demo("1111");//创建对象

Demo d2 = new Demo("2222");

Thread t1 = new Thread(d1);//创建线程

Thread t2 = new Thread(d2);

t1.start();//开启线程

t2.start();

}

}

总结:这两种方式建议是同第二种,第一种采用继承的方式,弊端非常明显,该类继承了Thread线程类就无法再去继承其他类了,这样提高了程序的耦合性,第二开发中常用

三、线程在程序中的几种状态

出生(Thread t = new Thread)--->就绪(t.start()准备执行)--->执行(获得CPU执行权)

执行--->等待(t.wait()):线程处于等待状态,自己醒不了,只能用notify()或者notifyAll()唤醒,处于等待状态的线程会释放CPU执行权,同时释放锁资源---->就绪(唤醒了)

执行--->睡眠(t.sleep()):在制定的毫秒数内让当前正在执行的线程休眠(并不是永久),只是暂停执行,它会释放CPU执行权,但是并不会释放锁资源,设定的毫秒时间到了,就会脱离睡眠状态

执行--->阻塞,当多条线程存在输入输出时,就会出阻塞状态

执行--->死亡,run方法执行完毕,线程就结束了也就是处于死亡状态

 

四、多线程的安全隐患以及synchronized监视器(锁)

多线程如果操作共享数据的多条语句,就有可能出现数据错乱问题

这个时候就需要用到多线程的同步机制,synchronized同步机制,

1.同步代码块:同步机制用于代码块中:

Object lock = new Object();

public void run( ){

synchronized(lock) { //这就是所谓的锁,开发常用这样方式解决线程同步问题

........code......

}

}

2.同步方法 :

public synchronized void run() {

........code............

}

总结:使用同步代码块可以解决线程安全问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值