一、线程有两种创建方式:
第一、继续Thread父类,重写run()方法。
public class MyThread extends Thread{
public void run(){
//执行一些方法
}
}
MyThread.start();
第二、实现Runnable类,覆盖run()方法,然后传入Thread对象中。
public class MyRunnable implement Runnable{
public void run(){
//执行某些方法
}
}
Thread thread = new Thread(MyRunnable);
thread.start();
可能遇到的疑惑:
问:为什么不直接调用run()方法而是去调用start()?
答:首先我们要直接thread类中的start()方法也是调用了其run()方法的。然后我们要明白这是线程。如果直接调用run()方法,这还是在主线程上运行,代码还是在程序中按顺序执行,所以不能解决耗时的问题。但是当你通过start()调用run()方法,这样子线程就会有异步的效果了。
二、同步代码块
同步块(synchronized block)可以标记在方法或者代码块上,java同步块是用来避免竞争的。
同步就是:一个对象同一时间只能为一个同步代码块服务
同步代码块需要传递的对象(锁对象):就是锁住这个对象,表示这个对象正在为我服务,其他人不能用(非synchronized代码块、方法除外)。
同步方法:就是同步代码块,同步锁对象是this
同步静态方法:就是同步代码块,同步锁对象是类的class对象(Demo类里的静态方法锁对象就是Demo.class)
OK了,这就是同步原理。再说简单点(当一个对象被锁住之后,在该代码块之外去使用此对象的方法,只要遇到同步代码块,就会进入等待状态)
那什么是死锁?死锁必须是多个线程对象才能够产生的。
刚刚不是说了,一个被锁住的对象,外部不能够在去掉用他的synchronized方法了吗,可如果我偏要调用,那么就会等待,所以,死锁就是两个线程对象在同步代码块内互相调用,就会死锁。
实例:
public class Demo {
public static Demo a = new Demo();
public static Demo b = new Demo();
public void fun1(){
synchronized(a) {
System.out.println("fun1");
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
b.fun2();
}
}
public void fun2(){
synchronized(b) {
System.out.println("fun2");
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
a.fun1();
}
}
}
(加等待是为了更好的说明问题)
fun1方法中,锁住了a对象,使用b对象。
fun2方法中,锁住了b对象,使用a对象。
这就是互相等待。
你如果使用两个线程去调用这两个方法,就会死锁。