15、线程

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

进程:是一个正在执行中的程序。
          每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。
线程:就是进程中的一个独立的控制单元。线程在控制着进程的执行。一个进程中至少有一个线程。

1、创建线程的两种方式
 第一种:  继承Thread类
     子类覆盖父类中的run方法,将线程运行的代码存放在run中
    目的:将自定义代码存储在run方法。让线程运行。(为什么要覆盖run方法呢? Thread类用于描述线程。
 该类就定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法。也就是说Thread类中的run方法,用于存储线程要运行的代码。)
    建立子类对象的同时线程也被创建
      通过调用start方法开启线程
    该方法两个作用:启动线程,调用run方法。
 
class Demo extends Thread
{
 public void run()
 {
  for(int x=0; x<60; x++)
   System.out.println("demo run----"+x);
 }
}
class ThreadDemo
{
 public static void main(String[] args)
 {
  Demo d = new Demo();//创建好一个线程。
  d.start();//开启线程并执行该线程的run方法。
  //d.run();//仅仅是对象调用方法。而线程创建了,并没有运行。
  for(int x=0; x<60; x++)
   System.out.println("Hello World!--"+x);
 }
}
 
 第二种:实现Runnable接口
步骤:
   1,定义类实现Runnable接口
   2,覆盖Runnable接口中的run方法。
      将线程要运行的代码存放在该run方法中。
   3,通过Thread类建立线程对象。
   4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
      为什么要将Runnable接口的子类对象传递给Thread的构造函数。
      因为,自定义的run方法所属的对象是Runnable接口的子类对象。
      所以要让线程去指定指定对象的run方法。就必须明确该run方法所属对象。
    5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
 class Demo implements Runnable{
 public void run()
 {
 for(int x=0; x<60; x++)
 System.out.println("demo run----"+x);
}
}
 class ThreadDemo2
{
  public static void main(String[] args)
 {
  Demo demo = new Demo();
  Thread t1 = new Thread(demo);//创建了一个线程;
  t1.start();
  for(int x=0; x<60; x++)
  System.out.println("main run----"+x);
  }
}

实现方式和继承方式有什么区别呢?
实现方式好处:实现方式避免了单继承的局限性,在定义线程时,建议使用实现方法。
在定义线程时,建立使用实现方式。
两种方式区别:
继承Thread:线程代码存放Thread子类run方法中。
实现Runnable,线程代码存在接口的子类的run方法。
 
线程 同步:
好处:解决了线程的安全问题
弊端:相对降低了效率,因为同步外的线程都会判断同步锁, 当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率
同步前提:同步中有多个线程,并且使用同一把锁

同步代码块(synchronized)
格式:
synchronized (对象)
{
需要同步的代码;
}
同步可以解决安全问题的根本原因就在那个对象上。
该对象如同锁的功能。
 同步的前提:
同步需要两个或者两个以上的线程,多个线程使用的是同一个锁,未满足这两个条件,不能称其为同步。

同步函数
格式:
在函数上加上synchronized 修饰符即可。
思考:同步函数用的是哪个锁呢?
函数需要被对象调用。那么函数都有一个所属对象引用。就是this。所以同步函数使用的锁是this。
通过该程序进行验证。
使用两个线程来买票。
一个线程在同步代码块中。
一个线程在同步函数中。
都在执行买票动作。
class Ticket implements Runnable
{
 private int tick = 1000;
 Object obj = new Object();
 boolean flag = true;
 public void run()
 {
  if(flag)
  {
   while(true)
   {
    synchronized(obj)
    {
     show();
    }
   }
  }
  else
   while(true)
    show();
 }
 public synchronized void show()//this
 {
  synchronized(obj)
  {
   if(tick>0)
   {
    try{Thread.sleep(10);}catch(Exception e){}
    System.out.println(Thread.currentThread().getName()+"....code : "+ tick--);
   }
  }
 }
}
class DeadLockDemo
{
 public static void main(String[] args)
 {
  Ticket t = new Ticket();
  Thread t1 = new Thread(t);
  Thread t2 = new Thread(t);
  t1.start();
  try{Thread.sleep(10);}catch(Exception e){}
  t.flag = false;
  t2.start();
 }
}


 
 

 思考1 :wait(),notify(),notifyAll(),用来操作线程为什么定义在了Object 类中?
          这些方法存在与同步中。
          使用这些方法时必须要标识所属的同步的锁。
          锁可以是任意对象,所以任意对象调用的方法一定定义Object 类中。
 思考2 :wait(),sleep() ,yield()有什么区别?
     wait():释放cpu 执行权,释放锁。
     sleep():释放cpu 执行权,不释放锁
     yield():临时暂停,可以让线程是释放执行权。

停止线程
1. 定义循环结束标记
因为线程运行代码一般都是循环,只要控制了循环即可。
2. 使用interrupt (中断)方法。
该方法是结束线程的冻结状态,使线程回到运行状态中来。
注:stop 方法已经过时不再使用。
Lock
创建RenntranLock()对象 替代同步代码
Condition 替代了notify() wait() notifyall()方法 出现了 await,signal,signalall方法
在同步中没有锁,即使有执行权也不可能执行
停止线程,使用标志的方法
setDaemon() 后台结束线程
lock相对于synchronization更加面向对
readlock writelock
读写锁可以做一个缓存系统
线程同步工具类
Semaphore 实现信号灯功能,可以实现互斥锁的功能
CycliBarrier 大家彼此等待,大家集合好后开始
CountDownLatch 犹如倒计时的计时器
Exchanger 用于实现两个人之间的数据交换
 
队列
BlockingQueue 阻塞队列
threadpooltest
executor
newrunnable 代表一种任务
  executor.newfixedthreadpool() 创建固定的线程
  executor.newcachedthreadpool() 创建缓存的线程, 线程池的线程是动态的, 创建一个可根据需要创建新线程的线程池 executor.newsinglethreadexecutor() 创建单一线程
如何实现线程死掉后重新启动;可以搞一个线程池
callable 类似于runnable 不过callable有返回值。
completionService 将生产新的异步任务与使用已完成任务的结果分离开来的服务。生产者 submit 执行的任务。使用者 take 已完成的任务,并按照完成这些任务的顺序处理它们的结果。
  简述synchronized和java.util.concurrent.locks.Lock的异同?
主要相同点:Lock能完成synchronized所实现的所有功能
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。Lock还有更强大的功能,例如,它的tryLock方法可以非阻塞方式去拿锁。
  当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
分几种情况:
     1.其他方法前是否加了synchronized关键字,如果没加,则能。
     2.如果这个方法内部调用了wait,则可以进入其他synchronized方法。
     3.如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。
     4.如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值