进程 VS 线程
并发 VS 并行
实现线程两种方法:
1.extends Thread,重写run方法(class Thread implements Runnable)
2.implements Runnable接口,重写run方法
启动线程用cat.start() 为什么不是 cat.run()
原因:
cat.run是一个普通的方法,没有真正启动一个线程,就会把run方法执行完毕,才向下执行
真正实现多线程的是private native void start0();
源码分析:
start() -> start0(),线程并不一定立马执行,只是将线程变为可运行状态
private native void start0();
用户线程 VS 守护线程
守护线程当用户线程都运行结束后自动结束,如垃圾回收
thread.setDaemon(true);
线程的7种状态:NEW RUNNABLE BLOCKED WAITING TIMED_WAITING TERMINATED
public class States_ {
public static void main(String[] args) throws InterruptedException {
ThreadState threadState = new ThreadState();
System.out.println("线程的状态:" + threadState.getState());
threadState.start();
while (Thread.State.TERMINATED != threadState.getState()) {
System.out.println("线程的状态:" + threadState.getState());
Thread.sleep(500);
}
System.out.println("线程的状态:" + threadState.getState());
}
}
class ThreadState extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
System.out.println("线程执行~");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程同步:synchronized
可在用在方法上(同步方法)、代码块(同步代码块),要求多个线程的锁对象是同一个
private synchronized void sell() {
}
synchronized (对象) {}
同步方法(非静态)的锁对象默认为 this
同步方法(静态)的锁对象默认为 当前类.class
public class Syncronized_ {
public static void main(String[] args) {
Cat cat = new Cat();
cat.start();
Cat cat1 = new Cat();
cat1.start();
}
}
class Cat extends Thread {
static int ticketNum = 10;
static boolean loop = true;
@Override
public void run() {
while (loop) {
sell();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private synchronized void sell() {
if (ticketNum > 0) System.out.println(Thread.currentThread().getName() + "卖票:" + ticketNum--);
else loop = false;
}
}
修改如下:
方式一:同步方法(静态)的锁为当前类本身,是同一对象
private synchronized static void sell() {
if (ticketNum > 0) System.out.println(Thread.currentThread().getName() + "卖票:" + ticketNum--);
else loop = false;
}
方式二:代码块上锁,指定锁对象(只要是同一对象即可)
private void sell() {
synchronized (Syncronized_.class) {
if (ticketNum > 0) System.out.println(Thread.currentThread().getName() + "卖票:" + ticketNum--);
else loop = false;
}
}
方式三:
public class Syncronized_ {
public static void main(String[] args) {
Cat cat = new Cat();
new Thread(cat).start();
new Thread(cat).start();
}
}
class Cat implements Runnable {
static int ticketNum = 10;
static boolean loop = true;
@Override
public void run() {
while (loop) {
sell();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private synchronized void sell() {
if (ticketNum > 0) System.out.println(Thread.currentThread().getName() + "卖票:" + ticketNum--);
else loop = false;
}
}
public class Test {
public static void main(String[] args) {
Cat cat = new Cat();
cat.start();
Dog dog = new Dog();
Thread thread = new Thread(dog);
thread.start();
System.out.println("main主线程启动子线程,main主线程不会阻塞,会继续执行,主线程结束不影响子线程,主线程名:" + Thread.currentThread().getName());
}
}
class Cat extends Thread {
@Override
public void run() {
while (true) {
System.out.println("喵喵喵~ " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Dog implements Runnable {
@Override
public void run() {
while (true) {
System.out.println("汪汪汪~ " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
Cat cat = new Cat();
cat.setName("cat");
cat.setPriority(1);
cat.start();
System.out.println("main主线程启动子线程,main主线程不会阻塞,会继续执行,主线程结束不影响子线程,主线程名:" + Thread.currentThread().getName());
Thread.sleep(2 * 1000);
cat.interrupt();
cat.join();
System.out.println("join相当于插队到main线程中来,cat线程执行完毕后才执行主线程");
}
}
class Cat extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("喵喵喵~ " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("线程被中断~");
}
}
}
}
释放锁:
1.同步方法、同步代码块正常执行结束,或遇到return、break
2.同步方法、同步代码块异常结束,出现Error或Exception
3.调用wait()方法,当前线程暂停执行并释放锁
不释放锁:
1.调用sleep()、yield()方法,当前线程暂停执行并不释放锁
2.线程执行同步代码块时,其他线程调用该线程的suspend()方法将线程挂起,该线程不释放锁。
提示:避免使用suspend()和resume()控制线程,方法不再推荐使用