什么进程:正在执行的程序

什么是线程Thread:线程是进程的基本单位,一个进程中可以同时存在多个线程。

实现线程有两种方式:

  1. 继承Thread类
  2. 实现Runnable接口

继承Thread类

1
2
.start()  是开启多线程,并执行run()里面的代码,主程序还会继续执行后面的代码
.run() 是执行一个方法

例子:

Task1.java - 线程1

1
2
3
4
5
6
7
8
9
10
11
public class Task1 extends Thread{

@Override
public void run() {
//线程1
for (int i = 1; i <= 100; ++i) {
System.out.println("i = " + i);
}
}

}

Task2.java - 线程2

1
2
3
4
5
6
7
8
9
10
11
public class Task2 extends Thread {

@Override
public void run() {
//线程2
for (int j = 1; j <= 100; ++j) {
System.out.println("j = " + j);
}
}

}

Window.java - 主线程

1
2
3
4
5
6
7
8
9
10
11
public class Window {
public static void main(String[] args) {
//线程1
Task1 t1 = new Task1();
//线程2
Task2 t2 = new Task2();

t1.start();
t2.start();
}
}

静态方法:

1
2
3
4
5
6
7
8
9
10
11
12
1. Thread.yield()  时间礼让,可以在线程中写该方法,当执行到该方法时,会将CPU给其他线程

例如:
@Override
public void run() {
for (int i = 1; i <=10; ++i) {
System.out.println(i);
Thread.yield(); //线程礼让
}
}

2. Thread.sleep() 睡眠,单位是毫秒

实现Runnable接口

Task1.java - 线程1

1
2
3
4
5
6
7
8
9
10
11
public class Task1 implements Runnable {

@Override
public void run() {
//线程1
for (int i = 1; i <= 10; ++i) {
System.out.println("i = " + i);
}
}

}

Task2.java - 线程2

1
2
3
4
5
6
7
8
9
10
11
public class Task2 implements Runnable {

@Override
public void run() {
//线程2
for (int j = 1; j <= 10; ++j) {
System.out.println("j = " + j);
}
}

}

Window.java - 主程序

1
2
3
4
5
6
7
8
9
10
11
12
public class Window {
public static void main(String[] args) {
Runnable task1 = new Task1(); //Runnable
Runnable task2 = new Task2();

Thread t1 = new Thread(task1); //创建线程
Thread t2 = new Thread(task2);

t1.start(); //启动线程
t2.start();
}
}

最好实现Runnable,因为类是单继承的,减少继承的使用

线程安全问题

线程安全问题:当多个线程操作同一个共享数据时,引发的一种不正常的结果

如何解决:给公共代码块加上锁,通过sychronized

TicketSystem.java - 线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class TicketSystem implements Runnable {
public static int ticketNum = 20;

@Override
public void run() {
for (int i = 1; i <= 30; ++i) {
//给核心问题加锁
synchronized (TicketSystem.class) {
if (ticketNum >= 1) {
--ticketNum;
System.out.println("购票成功,剩余" + ticketNum);
}
}
}
}

}

Window.java - 主线程

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Window {
public static void main(String[] args) {
TicketSystem ts = new TicketSystem();

Thread t1 = new Thread(ts);
Thread t2 = new Thread(ts);
Thread t3 = new Thread(ts);

t1.start();
t2.start();
t3.start();
}
}

总结

实现线程有什么方式:

  1. 继承Thread类
  2. 实现Runnable接口

如何启动线程?直接执行run()和start()的区别?

​ .start()方法启动线程,run()只是执行普通的方法

什么情况下会发生线程安全问题:

​ 当多个线程操作同一个共享数据时

如何解决安全问题:

​ 同步加锁