线程
创建线程需要继承Thread类或者Runnable接口
我们先用一个实例来展示一下多线程
//创建一个卖票的实例
class tickts implements Runnable{
private int tickts=100;
public void run(){
while(true){
if(tickts>0){
System.out.println(Thread.currentThread().getName()+"......"+tickts--);
}
}
}
}
public class saletakets {
public static void main(String[] args) {
tickts t=new tickts();
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();
}
}
所谓多线程其实是通过分配从cpu所给的时间片来执行的
假设当票数为1时,t1执行到判断语句完毕时线程切换到t2,此时t1为阻塞状态。t2执行完毕后,票数变为0,然后cpu切换到t1,此时不执行判断语句,那么票数将输出0。(以此类推,就可能出现-1,-2等数据错误的现象)
原因就是:1.多个线程操作共享数据
2.线程任务操作共享数据的代码有多条(运算有多个)
解决方法: 将线程代码封装起来使用synchronized(同步代码块)
格式为:synchronized(任意对象){
//代码
}
接下来我们来看一下改写过的程序
class tickts implements Runnable{
private int tickts=100;
Object obj=new Object();
public void run(){
synchronized(obj){
while(true){
if(tickts>0){
System.out.println(Thread.currentThread().getName()+"......"+tickts--);
}
}
}
}
}
public class saletakets {
public static void main(String[] args) {
tickts t=new tickts();
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 tickts implements Runnable{
private int tickts=100;
Object obj= new Object();
public void run(){
sale();
}
public synchronized void sale(){ //使用同步函数
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(tickts>0){
System.out.println(Thread.currentThread().getName()+"......"+tickts--);
}
}
}
}
public class saletakets {
public static void main(String[] args) {
tickts t=new tickts();
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();
}
}
通过以上的例子我们发现同步函数的任意对象就是this
同步函数和同步代码块的区别:
同步函数使用的锁是固定的this,同步代码块锁是任意对象
当函数为Static 同步函数,使用的锁不是this 而是字节码文件对象 类名.class