创建线程的方式:
方式一:
1. 自定义一个类继承Thread类。
2. 重写Thread类的run方法 , 把自定义线程的任务代码写在run方法中
疑问: 重写run方法的目的是什么?
每个线程都有自己的任务代码,jvm创建的主线程的任务代码就是main方法中的所有代码, 自定义线程的任务代码就写在run方法中,自定义线程负责了run方法中代码。
3. 创建Thread的子类对象,并且调用start方法开启线程。
方式二:(推荐)
1. 自定义一个类实现Runnable接口。
2. 实现Runnable接口 的run方法,把自定义线程的任务定义在run方法上。
3. 创建Runnable实现类对象。
4. 创建Thread类 的对象,并且把Runnable实现类的对象作为实参传递。
5. 调用Thread对象 的start方法开启一个线程。
方式一:
1. 自定义一个类继承Thread类。
2. 重写Thread类的run方法 , 把自定义线程的任务代码写在run方法中
疑问: 重写run方法的目的是什么?
每个线程都有自己的任务代码,jvm创建的主线程的任务代码就是main方法中的所有代码, 自定义线程的任务代码就写在run方法中,自定义线程负责了run方法中代码。
3. 创建Thread的子类对象,并且调用start方法开启线程。
注意:一个线程一旦开启,那么线程就会执行run方法中的代码,run方法千万不能直接调用,直接调用run方法就相当调用了一个普通的方法而已,并没有开启新的线程。
public class Example extends Thread {
@Override
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("子线程启动了 当前i的值:"+ i);
}
}
public static void main(String[] args) {
Example object = new Example();
object.start(); // 启动子线程
for (int i = 0; i < 100; i++) {
System.out.println("主线程启动了 当前j的值"+ i);
}
}
}
eg:模拟QQ视频与聊天
class TalkThread extends Thread{
@Override
public void run() {
int i = 0;
while (i < 1000) {
System.out.println("两个人正在聊天 " + Thread.currentThread().getName()); // 取出线程名称
i++;
}
}
}
class VideoThread extends Thread{
boolean flag; // 标识视频是否已经打开
@Override
public void run() {
while (!flag) {
System.out.println("打开视频..."+ Thread.currentThread());
flag = true;
}
}
}
public class Example2 {
public static void main(String[] args) {
TalkThread t = new TalkThread();
t.setName("会话"); // 设置线程名称
VideoThread v = new VideoThread();
v.setName("视频");
t.start();
v.start();
}
}
eg: 卖票线程安全问题
class SaleTicket extends Thread{
static int ticket = 1000; // 100张票 数据必须是唯一的
public SaleTicket(String name) {
super(name);
}
@Override
public void run() {
while (true) {
synchronized ("ticket") { // 这个地方加锁
if (ticket > 0) {
ticket--;
System.out.println(Thread.currentThread().getName() + "卖出了一张票,剩余票数:"+ ticket);
} else {
System.out.println("没有票了!");
break;
}
}
}
}
}
public class Demo5 {
public static void main(String[] args) {
SaleTicket P1 = new SaleTicket("窗口1");
SaleTicket P2 = new SaleTicket("窗口2");
SaleTicket P3 = new SaleTicket("窗口3");
P1.start();
P2.start();
P3.start();
}
}
模拟银行取钱问题
class BankThread extends Thread {
static int money = 100000;
@Override
public void run() {
while (true) {
synchronized ("money") { // 加锁
if (money > 0) {
money -= 500;
System.out.println(Thread.currentThread().getName()+"取走了500块");
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Example3 {
public static void main(String[] args) {
BankThread m = new BankThread();
BankThread w = new BankThread();
m.setName("老公");
w.setName("老婆");
m.start();
w.start();
}
}
方式二:(推荐)
1. 自定义一个类实现Runnable接口。
2. 实现Runnable接口 的run方法,把自定义线程的任务定义在run方法上。
3. 创建Runnable实现类对象。
4. 创建Thread类 的对象,并且把Runnable实现类的对象作为实参传递。
5. 调用Thread对象 的start方法开启一个线程。
public class Example4 implements Runnable { // 1.实现Runnable接口
// 2.重写接口run()方法
@Override
public void run() {
// 子线程需要做的事情写这里面
for (int i = 0; i < 500; i++) {
System.out.println("子线程调用了" + i);
}
}
public static void main(String[] args) {
// 3.创建实现接口类的对象
Example4 obj = new Example4();
// 4.创建thread对象
Thread thread = new Thread(obj, "子线程");
// 5.调用start方法
thread.start();
for (int i = 0; i < 500; i++) {
System.out.println("主线程调用了" + i);
}
}
}
eg: 自定义类实现Runnable接口实现卖票案例
class SaleTickets implements Runnable
{
int ticket = 1000; // 总票数
@Override
public void run() {
while (ticket > 0) {
synchronized ("ticket") {
if (ticket > 0) {
ticket--;
System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余票数:" + ticket);
} else {
System.out.println("票卖完了");
}
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Example5 extends Thread{
public static void main(String[] args) {
// 创建1个卖票窗口
SaleTickets P = new SaleTickets();
// 开启3个线程同时卖票
Thread t1 = new Thread(P, "窗口1");
Thread t2 = new Thread(P, "窗口2");
Thread t3 = new Thread(P, "窗口3");
t1.start();
t2.start();
t3.start();
}
}