黑马程序员_JavaSE基础13 之 线程创建 线程安全 同步代码块

来源:互联网 发布:松江报警主机编程号 编辑:程序博客网 时间:2024/06/07 14:46
----------------------      android培训java培训、期待与您交流!   ---------------------
JavaSE_13  笔记 
                          Java语言基础之  线程创建  线程安全 同步代码块
 
1、 线程的四种状态
①创建——start();
②运行——run();
该状态下的线程具备CPU的执行资格(可以被处理,在处理对了中排队)和CPU的执行权(正在被cpu处理)。
③冻结——sleep(time);  wait() ; 唤醒——notify(); 
释放执行权,同时释放执行资格。
④消亡——stop();
 
2、创建线程的第二中方式——实现Runnable接口,
   ①使用情况:Java不支持多继承,当一个类已经继承了一个父亲时,为了实现多线程,便有了使用接口来扩展其功能。
   ②步骤:定义类实现Runnable接口;覆盖接口中的run方法,将线程的任务代码封装到run方法中;通过Thread类创建线程对象,并将Runnable接口的子类对象作为构造函数的参数进行传递;最后调用线程对象的start方法开启线程。
 
3、线程事例之卖票1 : 创建4个对象,不能实现共卖100张票。
class Ticket extends Thread
{
private int num=100;
public void run()
{
While(true)
{
If(num>0)
{
System.out.println(Thread.currentThread. getName()+”....sale......”num--);
}
}
}
}
 
class  TicketDemo//创建4个卖票对象,相当于开始了4个线程;而每个线程都执行一次卖100张票的过程
{
public static void main(String[] args) 
{
Ticket t1=new Ticket(); 
Ticket t2=new Ticket(); 
Ticket t3=new Ticket(); 
Ticket t4=new Ticket(); 
t1.start();
t2.start();
t3.start();
t4.start();
}
}
 
 
4、线程事例之卖票2 : 创建1个对象,能实现共卖100张票。
class Ticket implements Runnable
{
private int num=100;
public void run()
{
While(true)
{
If(num>0)
{
System.out.println(Thread.currentThread. getName()+”....sale......”num--);
}
}
}
}
 
class  TicketDemo//创建一个对象,却开启了4个线程共用一个对象,即Num.
{
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();
 
}
}
  
5、线程事例之卖票3 : 线程安全问题
If(num>0)  // 当thread-0拿到num=0,此时thread-1得到执行权,由于num还没有执行操作,还是0,所以会出现
{
System.out.println(Thread.currentThread. getName()+”....sale......”num--);
}
线程安全问题分析:
①多个线程在操作共享的数据;②操作共享数据的线程代码有多条。
 
6、线程安全问题解决方法:在java中,使用同步代码块来解决,就是把共享数据代码封装起来。
 ①格式: synchronized (对象) {  //需要被同步的代码;   }
 ②同步的好处:解决了线程的安全问题;同步的弊端:降低了效率,应为同步外的线程都会判断同步锁。
 ③同步的前提:同步中必须有多个线程并使用同一个锁。
 ④事例:
class Ticket implements Runnable
{
private int num=100;
Object obj=new Object(); // 创建锁,同时注意位置,不能再run()内,因为唯一.
public void run()
{
while(true)
{
synchronized(obj) //同步代码块
{
if(num>0)
{
System.out.println(Thread.currentThread().getName()+"....sale...."+ num--);//当前第几线程正在卖第几张票
}
}
}
}
}
 
7、线程事例之存钱 1: 有共享数据,存在数据安全问题。
//两个储户存款3次,每次存储100元
class Bank
{
 
private sum ; //线程安全问题1、有共享数据 sum ; 2、有多个线程操作
public void add(int num)
{
sum+=num;
}
}
 
class Cus implements Runnable
{
public void run()
{
Bank b=new Bank();
for(int i=0;i<3;i++)
{
b.run();
}
}
}
 
class  TicketDemo//创建一个对象,却开启了4个线程共用一个对象,即Num.
{
public static void main(String[] args) 
{
Cus s=new Cus();
Thread t1=new Thread(c);
Thread t2=new Thread(c);
t1.start();
t2.start();
}
}
 
8、线程事例之存钱 2: 使用同步代码块,加锁,来解决数据安全问题。
//两个储户存款3次,每次存储100元
class Bank
{
private sum ; 
Object obj=new Object();
synchronized(obj)  //解决方法,使用锁
{
public void add(int num)
{
sum+=num;
}
}
}
 
9、同步函数和同步代码块的区别:
①同步函数的锁是固定的this。
public synchronized void add(int num){ }
②同步代码块的锁是固定的this。
 
10、静态同步函数
  静态的同步函数使用的锁是该函数所属的字节码文件对象,可以用getClass方法获取,也可以使用当前  类名.class 表示。
 
 
                                                                  2012/9/09     By  Mary_k
 
原创粉丝点击