线程的创建与启动
javaApi中创建线程有继承Thread类和实现Runnable接口
-
继承Thread类:
public class ThreadTest02 extends Thread { int num = 100; @Override public void run() { while (num > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"窗口卖票:" + num--); } } }
public class MyTest { // 创建3个线程并启动 public static void main(String[] args) { ThreadTest02 threadTest02_01 = new ThreadTest02(); ThreadTest02 threadTest02_02 = new ThreadTest02(); ThreadTest02 threadTest02_03 = new ThreadTest02(); threadTest02_01.start(); threadTest02_02.start(); threadTest02_03.start(); } }
-
实现Runnable接口
public class ThreadTest01 implements Runnable { int num = 100; @Override public void run() { while (num > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"窗口卖票:" + num--); } } }
public class MyTest { public static void main(String[] args) { ThreadTest01 threadTest01 = new ThreadTest01(); Thread thread01 = new Thread(threadTest01); Thread thread02 = new Thread(threadTest01); Thread thread03 = new Thread(threadTest01); thread01.start(); thread02.start(); thread03.start(); } }
Thread类有关的方法
void start()
: 启动线程,并执行对象的run()方法run()
: 线程在被调度时执行的操作String getName()
: 返回线程的名称void setName(String name)
:设置该线程名称static Thread currentThread()
: 返回当前线程。在Thread子类中就是this,通常用于主线程和Runnable实现类static void yield()
:线程让步暂停当前正在执行的线程,把执行机会让给优先级相同或更高的线程若队列中没有同优先级的线程,忽略此方法join()
: 当某个程序执行流中调用其他线程的 join() 方法时,调用线程将被阻塞,直到 join() 方法加入的 join 线程执行完为止(低优先级的线程也可以获得执行)static void sleep(long millis)
:(指定时间:毫秒)令当前活动线程在指定时间段内放弃对CPU控制,使其他线程有机会被执行,时间到后重排队。 抛出InterruptedException异常stop()
: 强制线程生命期结束,不推荐使用boolean isAlive()
: : 返回boolean,判断线程是否还活着
如:join方法示例,以下代码在main线程中调用t1线程的join方法,会阻塞main线程,直到t1线程执行完毕
public class ThreadTest06 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "->执行");
}
}, "t1");
t1.start();
Thread.sleep(1000);
t1.join();
System.out.println(Thread.currentThread().getName()+"->执行");
}
}
线程同步问题
如下代码,3个线程同时抢票
public class ThreadTest01 implements Runnable {
int num = 100;
@Override
public void run() {
while (num > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"窗口卖票:" + num--);
}
}
public static void main(String[] args) {
ThreadTest01 threadTest01 = new ThreadTest01();
Thread thread01 = new Thread(threadTest01);
Thread thread02 = new Thread(threadTest01);
Thread thread03 = new Thread(threadTest01);
thread01.start();
thread02.start();
thread03.start();
}
}
运行结果:会出现错票和重复票问题
Thread-0窗口卖票:2
Thread-1窗口卖票:2
Thread-1窗口卖票:1
Thread-0窗口卖票:-1
Thread-2窗口卖票:0
- 多线程出现了安全问题
- 问题 的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有
执行完,另一个线程参与进来执行。导致共享数据的错误。 - 解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以
参与执行
Java 对于多线程的安全问题提供了专业的解决方式 : 同步
-
同步代码块 :
synchronized ( 对象){
// 需要被同步的代码;
} -
synchronized 还可以放在方法声明中,表示 整个方法为 同步方法 。
例如:
public synchronized void show (String name){
….
}
线程死锁问题
- 死锁
- 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃
自己需要的同步资源,就形成了线程的死锁- 出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于
阻塞状态,无法继续
- 解决方法
专门的算法、原则
尽量减少同步资源的定义
尽量避免嵌套同步
线程死锁代码:执行结果是线程一直
线程死锁代码:
public class DeadLock {
public synchronized void method01(DeadLock02 deadLock02) {
System.out.println(Thread.currentThread().getName() + "->method01执行");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"->method01执行,准备调用deadLock02.method");
deadLock02.method(this);
}
public static void main(String[] args) throws InterruptedException {
DeadLock deadLock = new DeadLock();
DeadLock02 deadLock02 = new DeadLock02();
new Thread(new Runnable() {
@Override
public void run() {
deadLock.method01(deadLock02);
}
}).start();
Thread.sleep(500);
deadLock02.method(deadLock);
}
}
class DeadLock02{
public synchronized void method(DeadLock deadLock) {
System.out.println(Thread.currentThread().getName() + " ->DeadLock02的method03执行,准备调用deadLock.method01");
deadLock.method01(this);
}
}