JAVA 10(多线程)

 
创建线程:
通过对java.lang包的查找,继承Thread类可以创建线程
 
1,建立类继承Thread类
2,复写Thread中的ran方法。
3,调用线程的start()方法,该方法的作用是,启动线程,调用ran方法。
 
 
public class Test {
 public static void main(String args[])
 {
  Demo a= new Demo();
  a.start();
  for(int x=0;x<=100;x++)
  System.out.println("hello word");
 }
 
}
class Demo extends Thread
{
 public void ran()
 {
  for(int x=0;x<=100;x++)
  System.out.println("Demo ran");
 }
}
 
 
两个输出会交替出现。
发现运行结果每次都不同
因为多个线程都在获取cpu的使用权,cpu执行到谁,谁就运行,在某一时刻,只能有一个程序在运行(多核除外)cpu在做着快速切换,已达到看上去是在同时运行。
 
多线程特性:随机性,谁抢到谁执行,至于执行多长时间,cpu说的算。
 
为什么要覆盖ran方法
thread类用于描述线程。
该类定义了用于存储要运行的代码,这些代码就存储在ran方法中。
 
ran() 和 start() 区别
 
只写ran()线程没有被创建,编程了单线程程序。会顺序执行,输出不是随机的。
 
 
线程运行过程中的状态:
 
 
 
 
线程对象的名称:
每个线程都有默认名称。
Thread-编号   //该编号从0开始
线程名称可以提供 线程.getName()  方法获得
 
currentThread() :获取当前运行的线程对象
getName():获取线程名称
 
 
 
买票程序举例:
 
public class Test
{
 public static void main(String args [])
 {
  Ticket t1 = new Ticket();
  Ticket t2 = new Ticket();
  Ticket t3 = new Ticket();
  Ticket t4 = new Ticket();
  Ticket t5 = new Ticket();
 
  t1.start();
  t2.start();
  t3.start();
  t4.start();
  t5.start();
 
 }
}
 
 
class Ticket extends Thread
{
 private static int tick=100; //静态,所有对象公用一个票数。
 public void run()
 {
  if(tick>0)
  System.out.println(currentThread().getName()+"sale:"+tick--);
 }
}
 
 
第二种创建进程的方法
 
实现runable接口
 
步骤:
1,定义类,实现runnable接口
2,覆盖runnable中的run()方法
3,通过Thread;类建立线程对象
4,将Runnable接口对象作为实际参数传递给Thread类的构造函数
5,调用Thread类的start方法开启线程并调用Runnable子类中的run方法
 
实现方式和前一种方法的区别:
实现方式好处在于:避免了单继承的局限性。
在定义线程时,建议使用实现方式。
继承Thread类:线程代码存放在Thread子类对象run方法中
实现Runnable:线程代码存放在接口的子类对象的run中
 
在此例中ticket也不用static了,因为只建立了一个对象
  
 
睡眠:
try
     {Thread.sleep(10);}
     catch(Exception e)
     {
     
     }
 
 
 
public class Test
{
 public static void main(String args [])
 {
  Ticket t = new Ticket();
 
 
  Thread t1 =new Thread(t);
  Thread t2 =new Thread(t);
  Thread t3 =new Thread(t);
  Thread t4 =new Thread(t);
  t1.start();
  t2.start();
  t3.start();
  t4.start();
 }
}
class Ticket implements Runnable
{
 private int tick = 100;
 public void run()
 {
  while(true)
   if(tick>0)
   {
    System.out.println("sale"+tick--);
   }
 
 }
}
 
 
 
安全问题:
以下代码会打印  0,-1,-2号票
产生问题原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,另一个线程1参与进来执行,导致共享数据出现错误。 
 
解决办法:对多条操作共享数据的语句,只能让让一个线程都执行完,在执行过程中,其他线程不可以参与执行。 
 
java对于多线程的安全问题提供了专业的解决方式,就是同步代码块。会保证该代码块内的代码被全部执行再切换线程。
格式:
synchronized(对象)
{
需要被同步的代码
}
 
 
 
 
 
public class Test
{
 public static void main(String args [])
 {
  Ticket t = new Ticket();
 
 
  Thread t1 =new Thread(t);
  Thread t2 =new Thread(t);
  Thread t3 =new Thread(t);
  Thread t4 =new Thread(t);
  t1.start();
  t2.start();
  t3.start();
  t4.start();
 }
}
 
 
class Ticket implements Runnable
{
 private int tick = 100;
 public void run()
 {
  while(true)
   if(tick>0)
   {
    try
    {Thread.sleep(10);}
    catch(Exception e)
    {
     
    }
    System.out.println("sale"+tick--);
   }
 
 }
}
 
修改安全问题后的代码
 
 
 
 
public class Test
{
 public static void main(String args [])
 {
  Ticket t = new Ticket();
 
 
  Thread t1 =new Thread(t);
  Thread t2 =new Thread(t);
  Thread t3 =new Thread(t);
  Thread t4 =new Thread(t);
  t1.start();
  t2.start();
  t3.start();
  t4.start();
 }
}
 
 
class Ticket implements Runnable
{
 Object obj= new Object();
 private int tick = 100;
 public void run()
 {
  while(true)
  {
   synchronized(obj)
   {
    if(tick>0)
    {
     try
     {Thread.sleep(10);}
     catch(Exception e)
     {
     
     }
     System.out.println("sale"+tick--);
    }
   }
   
 
 }
  }
}
 
 
如何找到安全问题/同步的前提:
1,明确哪些代码是多线程运行的代码。
2,明确共享数据。
3,明确多线程代码中哪些语句是操作共享数据的。
 
 
同步函数:
同步有两种,1代码块,2同步函数
用synchronized修饰函数即可。
 
同步代码块使用的锁时obj
 
同步函数的锁:
同步函数使用的所时this  也就是调用该函数的实体。
如果同步函数被静态修饰后,使用的锁是该类对应的class,就是类名点class 。   Ticket.class
 
懒汉式
 
 
 
 
死锁:
 
两个锁:
同步中嵌套同步,锁却不同,恰好停止在某位置,会造成死锁。
要避免死锁。
 
 
 
public class Test
{
 public static void main(String args [])
 {
  Thread t1 = new Thread(new Deadlock(true));
  Thread t2 = new Thread(new Deadlock(false));
  t1.start();
  t2.start();
 }
}
 
class Deadlock implements Runnable
{
 private boolean flag;
 
 Deadlock(boolean flag)
 {
  this.flag = flag;
 }
 public void run()
 {
  if(flag)
  {
   while(true)
   {
   synchronized(Mylock.locka)
   {
    System.out.println("if lock a");
    synchronized(Mylock.lockb)
    {
     System.out.println("if lockb");
    }
   }
  }
  }
  else
  {
   while(true)
   {
   synchronized(Mylock.lockb)
   {
   
    System.out.println("else lockb");
    synchronized(Mylock.locka)
    {
     System.out.println("else locka");
    }
   }
   }
  }
 }
}
 
class Mylock
{
 static Object locka = new Object();
 static Object lockb = new Object();
}

 

posted @ 2015-07-25 15:15  hitz&x  阅读(326)  评论(0编辑  收藏  举报