0
点赞
收藏
分享

微信扫一扫

多线程学习笔记


多线程学习笔记

一、线程 | 进程 | 多线程

线程:操作系统能够进行运算调度的最小单位、线程是独立调度和分派的基本单位、同一进程中的多条线程将共享该进程中的全部系统资源。一个进程可以有很多线程,每条线程并行执行不同的任务

进程:系统进行资源分配和调度的基本单位(进程是执行程序的一次过程。程序:是指令和数据的有序集合,静态)

多线程:从软件或者硬件上实现多个线程并发执行的技术。(并发:时间片轮回,每隔一段时间处理不同的程序,时间短。并行:同时运行)

二、创建方式

1、继承Thread类

  • 继承Thread类
  • 重写run方法
  • 开启线程

package com.zheng.demo1;

public class MyThread1 extends Thread {
public static void main(String[] args) {
MyThread1 myThread1 = new MyThread1();
myThread1.start();

for (int i = 0; i < 100; i++) {
System.out.println("======我是主线程====" + i);
}

}

public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("我是子线程====" + i);
}
}
}

测试结果:

多线程学习笔记_多线程


线程开启后,主线程和子线程交替执行

2、实现runnable接口

  • 实现Runnable接口
  • 重写run()方法,编写线程执行体
  • 创建线程对象,开启线程

package com.zheng.demo1;

public class MyRunnable implements Runnable {
public static void main(String[] args) {

MyRunnable myRunnable = new MyRunnable();
// Thread thread = new Thread(myRunnable);
// thread.start();

new Thread(myRunnable).start();

for (int i = 0; i < 200; i++) {
System.out.println("-------我是主线程------" + i);

}
}

public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("我是子线程------" + i);

}
}
}

测试结果

多线程学习笔记_函数式接口_02


当创建多个对象,都开启线程。每一个对象都会独享一份重写run()里的资源

package com.zheng.demo1;

public class MyRunnable implements Runnable {
public static void main(String[] args) {

MyRunnable myRunnable = new MyRunnable();
MyRunnable myRunnable1 = new MyRunnable();
MyRunnable myRunnable2 = new MyRunnable();
MyRunnable myRunnable3 = new MyRunnable();

new Thread(myRunnable).start();
new Thread(myRunnable1).start();
new Thread(myRunnable2).start();
new Thread(myRunnable3).start();

for (int i = 0; i < 200; i++) {
System.out.println("-------我是主线程------" + i);

}
}

public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("我是子线程------" + i);

}
}
}

测试结果

多线程学习笔记_函数式接口_03


不安全购票行为

package com.zheng.demo1;

public class MyRunnable2 implements Runnable {
private int ticket = 9;


public static void main(String[] args) {
MyRunnable2 station = new MyRunnable2();
new Thread(station, "小明").start();
new Thread(station, "老师").start();
new Thread(station, "商贩").start();

}


public void run() {
while (true) {
if (ticket <= 0) {
break;//跳出循环
}
try {
Thread.sleep(1000);//模拟延时
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "买了第" + ticket-- + "张票");
}
}


}


测试结果

多线程学习笔记_多线程_04

龟兔赛跑问题

package com.zheng.demo1;

public class Game implements Runnable {
//只能有一个胜利者
private String winner;

public void run() {
for (int i = 0; i <= 100; i++) {
boolean flag = gameOver(i);
if (Thread.currentThread().getName() == "兔子" && i % 10 == 0) {
try {
Thread.sleep(5);//模拟兔子休眠
} catch (InterruptedException e) {
e.printStackTrace();
}

}
if (!flag) {
System.out.println(Thread.currentThread().getName() + "跑了" + i + "米");
} else {
break;
}
}

}


//判断比赛是否结束
public boolean gameOver(int step) {
if (winner != null) {
return true;
} else {
//继续跑
if (step >= 100) {
winner = Thread.currentThread().getName();//得到当前线程对象名
System.out.println("胜利者是:" + winner);
return true;
}
}

return false;
}

public static void main(String[] args) {
Game animal = new Game();
new Thread(animal, "兔子").start();
new Thread(animal, "乌龟").start();
}

}

测试结果

多线程学习笔记_子线程_05

3、Callable接口
4、lambda

三、静态代理

真实对象和代理对象都要实现同一个接口,代理对象要代理真实对象,真实对象关注自己主要的事情

package com.zheng.demo2;

public interface Wedding {
public void wedding();

}

//真实角色
class You implements Wedding {
public You() {
}

public void wedding() {
System.out.println("结婚了好开心");
}
}

//代理角色
class WeddingCompang implements Wedding {
private Wedding target;
public WeddingCompang(Wedding target) {
this.target = target;//要结婚的对象
}

public void wedding() {
before();
target.wedding();
after();
}

public void before() {
System.out.println("进行婚礼布置");
}

public void after() {
System.out.println("进行婚后的处理");
}

}


package com.zheng.demo2;

public class Mytest {
public static void main(String[] args) {
Wedding you = new You();
WeddingCompang wc = new WeddingCompang(you);
wc.wedding();

}
}

测试结果

多线程学习笔记_多线程_06

四、Lamda表达式

1、函数式接口(Function interface)

  • 定义:只包含一个抽象方法

public interface Runnable{
public abstract void run();
}

【1】

package com.zheng.demo3;


//定义函数式接口
interface A {
public void say();
}

class B implements A {
public void say() {
System.out.println("我是函数式接口");
}

}

public class Lamda {
public static void main(String[] args) {
B b = new B();
b.say();

}

}

静态内部类:静态内部类定义在类中,任何方法外,用static定义。

package com.zheng.demo3;


//定义函数式接口
interface A {
public void say();
}

public class Lamda {

//静态内部类
static class B1 implements A {
public void say() {
System.out.println("我是函数式接口1");
}

}

public static void main(String[] args) {
B1 b = new B1();
b.say();

}

}

多线程学习笔记_函数式接口_07


局部内部类:写在方法里边的类

package com.zheng.demo3;


//定义函数式接口
interface A {
public void say();
}

public class Lamda {

public static void main(String[] args) {
//局部内部类
class B2 implements A {
public void say() {
System.out.println("我是函数式接口2");
}

}

B2 b = new B2();
b.say();

}

}

多线程学习笔记_多线程_08


匿名内部类:匿名类是不能有名字的类,它们不能被引用,只能在创建时用New语句来声明它们

package com.zheng.demo3;


//定义函数式接口
interface A {
public void say();
}

public class Lamda {

public static void main(String[] args) {

//匿名内部类,没有类的名称,必须借助父类或者接口
A a=new A() {
public void say() {
System.out.println("我是匿名内部类");
}
};

a.say();



}

}

多线程学习笔记_函数式接口_09


lamda表达式

package com.zheng.demo3;


//定义函数式接口
interface A {
public void say();
}

public class Lamda {

public static void main(String[] args) {
//使用lamda表达式
A a1 = () -> {
System.out.println("我是lamda表达式");
};

a1.say();


}

}

多线程学习笔记_函数式接口_10

五、线程状态

1、新建状态

  • 2、就绪状态
  • 3、运行状态
  • 4、阻塞状态
  • 5、死亡状态
  • 多线程学习笔记_函数式接口_11

  • 线程停止:(使用标志位)

package com.zheng.demo4;

public class ThreadStop implements Runnable {
boolean flag = true;

public void run() {
int i = 0;
while (flag) {
System.out.println("我是子线程======" + i++);
}

}

//设置标志位用来停下线程
public void stop() {
this.flag = false;
}

public static void main(String[] args) {
ThreadStop threadStop = new ThreadStop();
new Thread(threadStop).start();

for (int i = 0; i < 50; i++) {
System.out.println("======我是主线程=====" + i);
if (i == 25) {
threadStop.stop();
System.out.println("子线程停止了");
}

}
}

}

测试结果

多线程学习笔记_函数式接口_12


1、线程休眠:模拟网络延时,放大问题发生的可能性,找到问题

    try {
Thread.sleep(1000);//模拟延时
} catch (InterruptedException e) {
e.printStackTrace();
}

打印当前的年月日时间

package com.zheng.demo4;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateSleep {
public static void main(String[] args) {
//获取系统当前时间
Date date = new Date(System.currentTimeMillis());

while (true){
try {
Thread.sleep(1000);//休眠一秒钟
String date1=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
System.out.println(date1);
date = new Date(System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

多线程学习笔记_i++_13


2、线程礼让,让当前执行的线程先暂停转化为就绪状态

package com.zheng.demo4;

public class MyYield {
public static void main(String[] args) {
YieldMy my = new YieldMy();
new Thread(my,"小明").start();
new Thread(my,"老师").start();

}
}

class YieldMy implements Runnable{

public void run() {
System.out.println(Thread.currentThread().getName()+"开始执行");
Thread.yield();//线程礼让
System.out.println(Thread.currentThread().getName()+"结束执行");

}
}

多线程学习笔记_多线程_14


3、线程的加入(join):加入的线程执行结束后,在执行其他的线程,其他线程阻塞

package com.zheng.demo4;

public class TestJoin implements Runnable {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("我是加入的线程" + i);

}
}

public static void main(String[] args) throws InterruptedException {
TestJoin testJoin = new TestJoin();
Thread thread = new Thread(testJoin);
thread.start();//开启线程

for (int i = 0; i < 20; i++) {
System.out.println("我是主线程" + i);
if (i == 15) {
thread.join();
}

}
}
}

多线程学习笔记_子线程_15


4、线程优先级

package com.zheng.demo4;

public class TestPriority {


public static void main(String[] args) {
Priority priority = new Priority();
Thread t1 = new Thread(priority);
Thread t2 = new Thread(priority);
Thread t3 = new Thread(priority);
Thread t4 = new Thread(priority);

Thread t6 = new Thread(priority);
Thread t7 = new Thread(priority);
Thread t8 = new Thread(priority);
Thread t9 = new Thread(priority);
Thread t10 = new Thread(priority);

System.out.println("当前线程名称:" + Thread.currentThread().getName() + " 优先级:" + Thread.currentThread().getPriority());


//设置线程优先级
t1.setPriority(Thread.MIN_PRIORITY);
t10.setPriority(Thread.MAX_PRIORITY);

t2.setPriority(2);
t3.setPriority(3);
t4.setPriority(4);

t6.setPriority(6);
t7.setPriority(7);
t8.setPriority(8);
t9.setPriority(9);

//开启线程
t1.start();
t2.start();
t3.start();
t4.start();

t6.start();
t7.start();
t8.start();
t9.start();
t10.start();
}

}

class Priority implements Runnable {
public void run() {
//打印当前线程名称+优先级
System.out.println("当前线程名称:" + Thread.currentThread().getName() + " 优先级:" + Thread.currentThread().getPriority());
}
}

测试结果

多线程学习笔记_多线程_16


优先级高代表CPU调度到的概率大。优先级低代表CPU调度到的概率低

5、守护线程
用户线程和守护线程,虚拟机必须保证用户线程执行完毕。不需要等待守护线程执行结束

package com.zheng.demo4;

public class Test {
public static void main(String[] args) {
People people = new People();
Animal animal = new Animal();
Thread thread = new Thread(animal);
thread.setDaemon(true);//默认是false为用户线程,true改为守护线程
thread.start();
new Thread(people).start();
}
}

class People implements Runnable {

@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("开心的生活");

}
}
}


class Animal implements Runnable {

@Override
public void run() {
while (true) {
System.out.println("动物守护着你");
}
}
}

测试结果

多线程学习笔记_多线程_17


守护线程不会一直执行下去,当用户线程结束后,虚拟机关闭

六、线程同步不安全实例

package com.zheng.demo5;


public class BuyTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(ticket, "小明").start();
new Thread(ticket, "老师").start();
new Thread(ticket, "商贩").start();
}
}

class Ticket implements Runnable {

private int ticket = 15; //票数
boolean flag = true;//设置标志位

public void buyTicket() {
if (ticket > 0) {//有票可以继续买
System.out.println(Thread.currentThread().getName() + "买了第" + ticket-- + "张票");
} else {
//无票
flag = false;//改变标志位状态,结束线程
}

}

@Override
public void run() {
while (flag) {
try {
Thread.sleep(50);//模拟买票延时
} catch (InterruptedException e) {
e.printStackTrace();
}
buyTicket();//调用买票的方法
}
}
}

多线程学习笔记_函数式接口_18


2、存钱取钱问题

package com.zheng.demo5;

public class Bank {
public static void main(String[] args) {
Account account = new Account(100, "买房");
withdrawMoney thread = new withdrawMoney(account,50,"小明");
withdrawMoney thread1 = new withdrawMoney(account,100,"小黑");
thread.start();
thread1.start();
}
}


class Account{
int money;
String name;
public Account(int money,String name){
this.money=money;
this.name=name;
}

}

class withdrawMoney extends Thread{

Account bank;

int nowMoney;
//取款金额
int takeMoney;
withdrawMoney(Account bank,int takeMoney,String name){
super(name);
this.bank=bank;
this.takeMoney=takeMoney;

}

@Override
public void run() {

//判断是否能取钱
if(bank.money-takeMoney<0){
System.out.println("余额不够");
return;
}else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
bank.money=bank.money-takeMoney;
nowMoney=nowMoney+takeMoney;
System.out.println("账户还剩下"+bank.money);
System.out.println(Thread.currentThread().getName()+"手里的钱"+nowMoney);

}

}
}

多线程学习笔记_子线程_19


同步锁

买票

package com.zheng.demo5;


public class BuyTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(ticket, "小明").start();
new Thread(ticket, "老师").start();
new Thread(ticket, "商贩").start();
}
}

class Ticket implements Runnable {

private int ticket = 15; //票数
boolean flag = true;//设置标志位

//同步方法
public synchronized void buyTicket() {
if (ticket > 0) {//有票可以继续买
System.out.println(Thread.currentThread().getName() + "买了第" + ticket-- + "张票");
} else {
//无票
flag = false;//改变标志位状态,结束线程
}

}

@Override
public void run() {
while (flag) {
try {
Thread.sleep(50);//模拟买票延时
} catch (InterruptedException e) {
e.printStackTrace();
}
buyTicket();//调用买票的方法
}
}
}

多线程学习笔记_多线程_20


取钱

同步块:synchronized(obj){}
obj:共享资源作为同步监视器

  • 第一个线程访问,锁定,访问结束,第二个线程访问,锁定。。。

package com.zheng.demo5;

public class Bank {
public static void main(String[] args) {
Account account = new Account(100, "买房");
withdrawMoney thread = new withdrawMoney(account,50,"小明");
withdrawMoney thread1 = new withdrawMoney(account,100,"小黑");
thread.start();
thread1.start();
}
}


class Account{
int money;
String name;
public Account(int money,String name){
this.money=money;
this.name=name;
}

}

class withdrawMoney extends Thread{

Account bank;

int nowMoney;
//取款金额
int takeMoney;
withdrawMoney(Account bank,int takeMoney,String name){
super(name);
this.bank=bank;
this.takeMoney=takeMoney;

}

@Override
public void run() {
synchronized (bank){
//判断是否能取钱
if(bank.money-takeMoney<0){
System.out.println("余额不够");
return;
}else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
bank.money=bank.money-takeMoney;
nowMoney=nowMoney+takeMoney;
System.out.println("账户还剩下"+bank.money);
System.out.println(Thread.currentThread().getName()+"手里的钱"+nowMoney);

}
}



}
}

多线程学习笔记_i++_21

七、死锁

多个线程各自占有一些共享资源,并且只有等待其他线程释放资源才能运行。A:我需要你给我钱,我才能给你货。B:我需要你给我货,我才能给你钱。

八、生产者和消费者问题

生产者将商品放入仓库,消费者从仓库中取走商品。

  • 仓库没有商品,生产者将商品放入仓库。有商品,则停止生产并且等待。直到消费者全部拿走
  • 仓库有商品,消费者取走,无商品,停止消费并且等待,生产者生产商品放入仓库

package com.zheng.demo6;

public class CustomerAndProducer {
public static void main(String[] args) {
Warehouse warehouse = new Warehouse();
new Producer(warehouse).start();
new Customer(warehouse).start();
}
}


//生产者
class Producer extends Thread {
Warehouse warehouse;

public Producer(Warehouse warehouse) {
this.warehouse = warehouse;
}

//生产
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("生产了" + i + "个商品");
warehouse.push(new Food(i));

}

}
}


//消费者
class Customer extends Thread {
Warehouse warehouse;

public Customer(Warehouse warehouse) {
this.warehouse = warehouse;
}

//消费
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("消费了" + warehouse.pop().id + "个商品");


}

}
}

//产品
class Food {
int id;

public Food(int id) {
this.id = id;
}
}

//缓冲区
class Warehouse {
//生产者仓库大小
Food[] foods = new Food[10];
//计数器
int count = 0;

//生产者放入商品
public synchronized void push(Food food) {
//先判断能否放入
if (count == foods.length) {
//已放满,通知消费者消费
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
//没有放满,继续放入产品
foods[count] = food;
count++;
this.notify();//通知消费者消费
}
}

//消费者消费商品
public synchronized Food pop() {
//先判断能否消费
if (count == 0) {
//等待生产者生产
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//可以消费
count--;
Food food = foods[count];
//通知生产者生产
this.notifyAll();


return food;
}


}

多线程学习笔记_i++_22


举报

相关推荐

0 条评论