黑马程序员_线程概述

来源:互联网 发布:体脂秤什么牌子 知乎 编辑:程序博客网 时间:2024/04/29 11:46


 ------- android培训java培训、期待与您交流! ----------


线程概述:

多线程好处:解决了多部分同时运行的问题。

多线程的弊端:线程太多回到效率的降低。

其实应用程序的执行都是cpu在做着快速的切换完成的,这个切换是随机的。

JVM启动时就启动了多个线程,至少有两个线程可以分析的出来。

1,执行main函数的线程,该线程的任务代码都定义在main函数中。

2,负责垃圾回收的线程

线程的创建:

创建线程方式一:继承Thread类。

1,定义一个类继承Thread类。

2,覆盖Thread类中的run方法。

3,直接创建Thread的子类对象创建线程。

4,调用start方法开启线程并调用线程的任务run方法执行。

可以通过Thread的getName获取线程的名称  Thread-编号(从0开始)

主线程的名字就是main。

创建线程的目的是为了开启一条执行路径,去运行指定的代码和其他代码实现同时运行。

而运行的指定代码就是这个执行路径的任务。

jvm创建的主线程的任务都定义在了主函数中。

而自定义的线程它的任务在哪儿呢?

Thread类用于描述线程,线程是需要任务的。所以Thread类也对任务的描述。

这个任务就通过Thread类中的run方法来体现。也就是说,run方法就是封装自定义线程运行任务的函数。 

run方法中定义就是线程要运行的任务代码。

开启线程是为了运行指定代码,所以只有继承Thread类,并复写run方法。

将运行的代码定义在run方法中即可。

创建线程的第二种方式:实现Runnable接口。

1,定义类实现Runnable接口。

2,覆盖接口中的run方法,将线程的任务代码封装到run方法中。

3,通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。

为什么?因为线程的任务都封装在Runnable接口子类对象的run方法中。

所以要在线程对象创建时就必须明确要运行的任务。

4,调用线程对象的start方法开启线程。

实现Runnable接口的好处:

1,将线程的任务从线程的子类中分离出来,进行了单独的封装。

按照面向对象的思想将任务的封装成对象。

2,避免了java单继承的局限性。

所以,创建线程的第二种方式较为常用。

class Demo implements Runnable//extends Fu//准备扩展Demo类的功能,让其中的内容可以作为

线程的任务执行


public void run() { show();}public void show(){for(int x=0; x<20; x++){System.out.println(Thread.currentThread().getName()+"....."+x);}}}class ThreadDemo{public static void main(String[] args){Demo d = new Demo(); Thread t1 = new Thread(d);Thread t2 = new Thread(d);t1.start();t2.start();} }


 

死锁的根源:

导致死锁的根源在于不适当的运用了synchronized”关键词来管理线程对特定对象的访问。

synchronized”关键词的作用是,确保在某个时刻只有一个线程被允许执行特定的代码块,

因此,被允许执行的线程首先必须拥有对变量或对象的排他性访问权。当线程访问对象是,

线程会给对象加锁,而这个锁导致其他也想访问同意对象的线程被阻塞,直至第一个

线程释放他加载对象上的锁。

死锁例子:

class MyLock{public static final Object locka = new Object();public static final Object lockb = new Object();}class DeadLockTest {public static void main(String[] args) {Test a = new Test(true);Test b = new Test(false);Thread t1 = new Thread(a);Thread t2 = new Thread(b);t1.start();t2.start();}}class Test implements Runnable{private boolean flag;Test(boolean flag){this.flag = flag;}public void run(){if(flag){while(true)synchronized(MyLock.locka){System.out.println(Thread.currentThread().getName()+"..if locka....");synchronized(MyLock.lockb)        {System.out.println(Thread.currentThread().getName()+"..if lockb....");}}}else{while(true)synchronized(MyLock.lockb){System.out.println(Thread.currentThread().getName()+"..else lockb....");synchronized(MyLock.locka){System.out.println(Thread.currentThread().getName()+"..else locka....");}}}}}class MyLock{public static final Object locka = new Object();public static final Object lockb = new Object();}class DeadLockTest {public static void main(String[] args) {Test a = new Test(true);Test b = new Test(false);Thread t1 = new Thread(a);Thread t2 = new Thread(b);t1.start();t2.start();}}


死锁的解决放法:

如果程序中有几个竞争资源的并发线程,那么保证均衡是很重要的。系统均衡是指每个线程在执行过程

中都能充分访问有限的资源。

1, 顺序访问资源

一个简单的办法就是给资源排上号,如果一个线程需要获取多个资源,那就一定按从小号获取开始。

如果上面程序中的else语句,锁的分配顺序也是locka lockb。那么就不会又死锁的出现。

避免占有并等待

我们知道,死锁一定是占有一个资源再同时去等待另外一个资源而可能导致的。

因此如果可以打破占有并等待,那事情就有所转机。



  ------- android培训java培训、期待与您交流! ----------

 

0 0
原创粉丝点击