黑马程序员_线程概述


 ------- 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值