多线程
线程的状态
CPU的执行资格:可以被CPU处理,在处理队列排队
CPU的执行权:正在被CPU处理
创建线程的第二种方式
class Demo implements Runnable
{
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();
}
}
- 定义类实现Runnable接口
- 覆盖接口中的run方法,将线程的任务代码封装到run方法中
- 通过Thread类创建线程对象并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递,为什么?-------因为线程中的任务都封装在Runnable接口子类对象run方法中,所以要在线程对象创建时就必须名曲要运行的任务
- 调用线程对象的start的方法开启线程
实现Runnable接口的好处:
- 将线程的任务从线程的子类中分离出来,进行了单独的封装,按照面向对象的思想将任务封装成了对象
- 避免了Java单继承的局限性
所以,创建线程的第二种方法较为常用
class Ticket implements Runnable //extends Thread
{
private int num=100;
public void run()
{
while(true)
{
if(num>0)
{
System.out.println(Thread.currentThread().getName()+".....sale...."+num--);
}
}
}
}
class TicketDemo
{
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);
/*
Ticket t1=new Ticket();
Ticket t2=new Ticket();
Ticket t3=new Ticket();
Ticket t4=new Ticket();
*/
t1.start();
t2.start();
t3.start();
t4.start();
}
}
同步代码块
线程安全为题产生的原因:
- 多个线程在操作共享的数据
- 操作的共享数据的线程代码有多条
当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会导致线程安全产生问题
可以用同步代码快来解决这个问题
格式: synchronize(对象) { 需要被同步的代码;}
同步的好处:解决了线程安全的问题
同步的弊端:相对降低了效率,因为同步外的线程都会判断同步锁
同步的前提:必须有多个线程并使用同一个锁
同步函数
public synchronize void add(int num){ }
同步函数的锁是this
同步函数的同步代码块的区别:
同步函数的锁是固定的this
同步代码块的锁是任意对象
建议使用同步代码块
静态的同步函数使用的锁是该函数所属字节码文件对象,可以用get.class方法获取,也可以用当前类名.class表示
public static Single getInstance()
{
Synchronized(Single.class){}
}
/*
加同步的单例设计模式————懒汉式
*/
class Single
{
private static Single s = null;
private Single(){}
public static void getInstance()
{
if(s==null)
{
synchronized(Single.class)
{
if(s==null)
s = new Single();
}
}
return s;
}
}