多线程创建
创建线程方式一:
- 继承Thread类,重写run()方法,调用start开启线程
- 线程开启不一定立刻执行,由CPU调度
- 不建议使用:避免OOP单继承局限性
public class TestThread extends Thread {
@Override
public void run() {
//run()方法线程体
for (int i = 0; i < 20; i++) {
System.out.println("代码" + i);
}
}
public static void main(String[] args) {
//main线程,主线程
//创建一个对象
TestThread th = new TestThread();
//调用start()方法开启线程 多条执行路径,主线程和子线程并行交替执行
th.start();
// th.run(); //调用run()方法只有主线程一条执行路径,
for (int i = 0; i < 20; i++) {
System.out.println("学习" + i);
}
//两条线程同时执行,交替执行
}
}
创建线程方式二:
- 实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法 (推荐:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用)
//创建线程方式2:实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法
public class TestThread3 implements Runnable{
@Override
public void run() {
//run()方法线程体
for (int i = 0; i < 200; i++) {
System.out.println("代码" + i);
}
}
public static void main(String[] args) {
//创建Runnbale接口的实现类对象
TestThread3 th = new TestThread3();
// //创建线程对象,通过线程对象来开启线程,代理
// Thread thread = new Thread(th);
// thread.start();
new Thread(th).start();
for (int i = 0; i < 2000; i++) {
System.out.println("学习" + i);
}
//两条线程同时执行,交替执行
}
}
多个线程同时开始(抢车票):
//抢车票
//多个线程操作同一个资源的情况下,线程不安全,数据紊乱
public class TestThread4 implements Runnable {
//票数
private int ticketNums = 10;
@Override
public void run() {
while (true) {
if (ticketNums <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "--->拿到了第" + ticketNums-- + "张票");
//模拟延时
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
TestThread4 ticket = new TestThread4();
// Thread thread1 = new Thread(ticket);
// thread1.start();
new Thread(ticket, "ming").start();
new Thread(ticket, "dd").start();
new Thread(ticket, "23").start();
}
}
龟兔赛跑问题(多线程的应用)
//龟兔赛跑问题
public class Race implements Runnable {
private static String winner;
@Override
public void run() {
for (int i = 0; i <=100; i++) {
if (Thread.currentThread().getName().equals("兔子") && i % 10 == 0) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//判断比赛是否结束
boolean flag = gameOver(i);
if (flag) {
break;
}
System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");
}
}
private boolean gameOver(int steps) {
//判断是否存在胜利者
if (winner != null) {
return true;
} {
if (steps >= 100) {
winner = Thread.currentThread().getName();
System.out.println("胜利者:" + winner);
return true;
}
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race, "乌龟").start();
new Thread(race, "兔子").start();
}
}
Callable接口:
- 可以定义返回值
- 可以抛出异常
静态代理模式总结:
- 真实对象和代理对象都要实现同一个接口
- 代理对象要代理真实角色
好处:
- 代理对象可以做很多真实对象做不了的事情
- 真实对象专注做自己的事情
// 静态代理模式总结:
//真实对象和代理对象都要实现同一个接口
//代理对象要代理真实角色
//
//好处:
//代理对象可以做很多真实对象做不了的事情
//真实对象专注做自己的事情
public class StaticProxy {
public static void main(String[] args) {
You you = new You();
WeddingCompany weddingCompany = new WeddingCompany(you);
weddingCompany.HappyMarry();
}
}
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() {
before();
this.target.HappyMarry();
after();
}
private void before() {
System.out.println("婚前准备");
}
private void after() {
System.out.println("收款");
}
}
匿名内部类:没有类的名称,必须借助接口或者父类
Lambda表达式:
- Lambda表达式只能有一行代码的情况下才能简化成一行,否则需要代码块(花括号{})包裹。
- 前提是接口为函数式接口
- 多个参数也可以去掉参数类型,要去掉都去掉,必须加上括号
线程休眠
- 每一个对象都有一把锁,sleep不会释放锁