五、多线程
1. 线程的创建
推荐实现Runnable接口,因为java是单继承的,这个机会给Thread了别的类也要继承就麻烦了。
- 继承Thread类:
//继承Thread重写run方法
class Solution extends Thread{
@Override
public void run(){
for (int i = 0; i < 50; i++) {
System.out.println("听歌");
}
}
public static void main(String[] args) {
//创建子类对象,启动
Solution solution = new Solution();
//如果这里改成run,则是方法的调用需要等run听歌完再写代码
//这里调用start方法是把线程交给cpu去执行,到时候就不管了
solution.start();
for (int i = 0; i < 50; i++) {
System.out.println("写代码");
}
}
}
- 实现Runnable接口:
//实现Runnable接口+重写run方法
//启动需创建实现类对象+Thread对象+start
class Solution extends Thread implements Runnable{
@Override
public void run(){
for (int i = 0; i < 50; i++) {
System.out.println("听歌");
}
}
public static void main(String[] args) {
//创建实现类对象
Solution solution = new Solution();
//创建代理类对象
Thread t = new Thread(solution);
t.start();
for (int i = 0; i < 50; i++) {
System.out.println("写代码");
}
}
}
- 实现Callable接口。
- 抢票,龟兔赛跑
抢票不同的线程访问唯一的资源(票数)
//并发需要保证线程安全
class Solution implements Runnable{
//票数
private int ticketNumns = 99;
@Override
public void run(){
while (true) {
if (ticketNumns < 0){
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " --> " +ticketNumns --);
}
}
public static void main(String[] args) {
//一份资源
Solution solution = new Solution();
System.out.println(Thread.currentThread().getName());
//多个代理
new Thread(solution,"tsc").start();
new Thread(solution,"dkm").start();
new Thread(solution,"ysx").start();
}
}
龟兔赛跑,不同线程访问各自的资源(步数)
public class Racer implements Runnable {
private static String winner;
@Override
public void run() {
for (int steps = 1; steps <= 100; steps++) {
//模拟休息
if (Thread.currentThread().getName().equals("tuzi")){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "-->" + steps);
//比赛是否结束
boolean flag = gameOver(steps);
if (flag)
break;
}
}
private boolean gameOver(int steps){
if (winner != null){
return true;
}else {
if (steps == 100){
winner = Thread.currentThread().getName();
System.out.println(winner);
return true;
}
}
return false;
}
public static void main(String[] args) {
Racer racer = new Racer();
new Thread(racer,"wugui").start();
new Thread(racer,"tuzi").start();
}
}
- 静态代理
这个类是写好的,动态代理这个类是动态构建出来的。
//接口结婚
class Solution{
public static void main(String[] args) {
new WeddingCompany(new You()).happyMarry();
//new Thread(线程对象).start()
}
}
interface Marry{
void happyMarry();
}
//真实角色
class You implements Marry{
@Override
public void happyMarry() {
System.out.println("结婚了!");
}
}
//代理结婚
class WeddingCompany implements Marry{
//真实角色
private Marry target;
public WeddingCompany(Marry target){
this.target = target;
}
@Override
public void happyMarry() {
ready();
this.target.happyMarry();
after();
}
private void ready(){
System.out.println("布置现场");
}
private void after(){
System.out.println("洞房花烛夜");
}
}
线程在start()之前和之后都做了别的事情。
- 推导lambda简化代码
先看使用内部类:
//简化线程的使用
public class Solution{ // implements Runnable
//静态内部类,不使用不会编译,使用才编译
static class Test implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("听歌");
}
}
}
public static void main(String[] args) {
new Thread(new Test()).start();
new Thread(new Test()).start();
}
}
//简化线程的使用
public class Solution{ // implements Runnable
public static void main(String[] args) {
//局部内部类(方法内部)
class Test2 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("听歌");
}
}
}
new Thread(new Test2()).start();
}
}
//简化线程的使用
public class Solution{ // implements Runnable
public static void main(String[] args) {
//匿名内部类(必须借助接口或者父类)
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("听歌");
}
}
}).start();
}
}
//简化线程的使用
public class Solution{ // implements Runnable
public static void main(String[] args) {
//lambda表达式,只关注线程体
new Thread(() -> {
for (int i = 0; i < 20 ; i++) {
System.out.println("听歌");
}
}).start();
}
}
- 线程状态