JAVA——多线程学习笔记
多线程
Thread接口
验证多线程同时进行 start()
public class Demo01 extends Thread {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("雷恩加尔");
}
}
public static void main(String[] args) {
Demo01 demo01 = new Demo01();
demo01.start();
for (int i = 0; i < 200; i++) {
System.out.println("雷克塞");
}
}
}
Runnable
龟兔赛跑和sleep()函数
public class Demo02 implements Runnable {
private static String winner;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
if(Thread.currentThread().getName().equals("兔子") && i % 20 == 0){
try {
Thread.sleep(5);//让兔子每五毫秒睡一次
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
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 is" + winner);
return true;
}
}
return false;
}
public static void main(String[] args) {
Demo02 race = new Demo02();
new Thread(race , "乌龟").start();
new Thread(race , "兔子").start();
}
}
Callable
静态代理
拉姆达表达式
public class LambdaExpress {
public static void main(String[] args) {
/* 旧版
Foo foo= new Foo() {
@Override
public void sayHello() {
System.out.println("一句话学习拉姆达表达式");
}
};
foo.sayHello(); */
//LambdaExpress版
Foo foo = ()->{ System.out.println("一句话学习拉姆达表式");};foo.sayHello()
静态代理的实现
//代理对象那个可以干真实对象干不了的事情
//真实对象可以高效做自己的事情
public class MarryDemo {
public static void main(String[] args) {
//用拉姆达表达式和线程实现
//new Thread(()->{System.out.println("I love you");}).start();
WedCompany wedCompany = new WedCompany(new You());
wedCompany.HappyMarry();
//精简后
//new WedCompany(new You()).HappyMarry();
}
}
interface Marry{ //接口 真实对象和代理对象都要实现同一个借口
void HappyMarry();
}
class You implements Marry{
@Override
public void HappyMarry() {
System.out.println("你要结婚了 , cao开心");
}
}
class WedCompany implements Marry{
private Marry target;
public WedCompany(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("结婚之后,收尾款");
}
}
Lamda表达式
public class Lamda {
//静态内部类
static class Like2 implements ILike{
@Override
public void lamda() {
System.out.println("lamda is what I liked 2");
}
}
public static void main(String[] args) {
Like1 like1 = new Like1();
like1.lamda();
Like2 like2 = new Like2();
like2.lamda();
//局部内部类
class Like3 implements ILike{
@Override
public void lamda() {
System.out.println("lamda is what I liked 3");
}
}
Like3 like3 = new Like3();
like3.lamda();
//匿名内部类 没有类的名称 必须借助接口或者父类
ILike like4 = new ILike() {
@Override
public void lamda() {
System.out.println("lambda is what I liked 4");
}
};
like4.lamda();
//lamda简化
ILike like = ()->{
System.out.println("lambda is what I liked 5");
};
like.lamda();
}
}
//定义一个函数式接口
interface ILike{
void lamda();
}
//外部类
class Like1 implements ILike{
@Override
public void lamda() {
System.out.println("lamda is what I liked 1");
}
}
- lamda表达式只能有一行代码的情况下才能简化为一行,如果有多行,那么就使用花括号
- 前提是接口为函数式接口
- 多个参数也可以去掉参数类型,要去掉就都求掉,必须叫上括号
线程休眠
倒数器
public class Stop {
public static void main(String[] args) {
try {
tenDown();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public static void tenDown() throws InterruptedException {
int num = 10;
while (true){
Thread.sleep(1000);
System.out.println(num--);
if(num <= 0){
break;
}
}
}
}
获取系统当下的时间
import javax.xml.crypto.Data;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Stop {
public static void main(String[] args) {
Date startTime = new Date(System.currentTimeMillis());//获取时间时间
while(true){
try {
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
startTime = new Date(System.currentTimeMillis());
//更新时间
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void tenDown() throws InterruptedException {
int num = 10;
while (true){
Thread.sleep(1000);
System.out.println(num--);
if(num <= 0){
break;
}
}
}
}
线程礼让
import java.lang.reflect.Field;
public class Yield {
public static void main(String[] args) {
Myyield myyield = new Myyield();
new Thread(myyield , "A").start();
new Thread(myyield , "B").start();
}
}
class Myyield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程开始执行!");
Thread.yield();
System.out.println(Thread.currentThread().getName() + "线程已经结束!");
}
}
线程强制执行
public class JoinD implements Runnable {
public static void main(String[] args) throws InterruptedException {
JoinD joinD = new JoinD();
Thread thread = new Thread(joinD);//代理
thread.start();
//创建主线程任务
for (int i = 0; i < 100; i++) {
if(i == 10){
thread.join();//插队
}
System.out.println("普通人");
}
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("vip");
}
}
}
线程优先级
public class PriorityD {
public static void main(String[] args) {
//主线程默认优先级
System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
MyPriority myPriority = new MyPriority();
Thread t1 = new Thread(myPriority);
Thread t2 = new Thread(myPriority);
Thread t3 = new Thread(myPriority);
Thread t4 = new Thread(myPriority);
Thread t5 = new Thread(myPriority);
Thread t6 = new Thread(myPriority);
//设置优先级
t5.setPriority(Thread.MAX_PRIORITY);
t5.start();
t1.start();
t2.setPriority(8);
t2.start();
t3.setPriority(3);
t3.start();
t4.setPriority(4);
t4.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
}
}
让我们考虑这么个例子,优先级 T1>T2>T3
- T3先执行,他执行的时候正好拿到了资源A,意味着别的任务不能访问资源A,而会被阻塞
- 这时 T2执行,由于优先级更高,他很轻松的抢占了CPU 然后他成功的访问到了资源B,成为唯一能够访问资源B,拿到锁的幸运儿。有趣的是,资源B也是T3所需要的,但是这不影响,因为按理来说,T2会执行,直到释放B的锁,以及让出CPU,这样T3可以继续执行
- 这时出现了T1,他毫不意外的从T2抢占了CPU,但是却没办法执行,因为缺乏资源A!所以理论上他需要T3执行完才能继续执行。。。TT
守护线程
public class DaemonD {
public static void main(String[] args) {
God god = new God();
You2 you = new You2();
Thread thread = new Thread(god);
thread.setDaemon(true);//默认都是false , 表示是用户线程
thread.start();//上帝守护线程启动
new Thread(you).start();//用户线程启动
}
}
class God implements Runnable{
@Override
public void run() {
while(true){
System.out.println("上帝守护着你!");
}
}
}
class You2 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("你一生幸福的活着!");
}
System.out.println("再见===========世界!");
}
}
三大不安全案例
购票问题
import static java.lang.Thread.sleep;
public class UnsafeDemo1 {
public static void main(String[] args) {
// Thread thread = new Thread(new BuyTicket() , "苦逼的我");
// thread.start();
// Thread thread1 = new Thread(new BuyTicket() , "abaaba"); 定义错误
// thread1.start(); 定义多个BuyTicket造成一个人一个。
// Thread thread2 = new Thread(new BuyTicket() , "adada");
// thread2.start();
BuyTicket buyTicket = new BuyTicket();
new Thread(buyTicket , "大学生").start();
new Thread(buyTicket , "社会人").start();
new Thread(buyTicket , "摆烂人").start();
}
}
class BuyTicket implements Runnable{
boolean flag = true;
private int TicketNumber = 10;
@Override
public void run() {
while(flag){
try {
Buy();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
private void Buy() throws InterruptedException {
if(TicketNumber <= 0)
{
flag = false;
return;
}
sleep(100);
System.out.println(Thread.currentThread().getName() + "拿到了第" + TicketNumber-- + "票");
}
}
银行问题
public class UnsafeDemo2 {
public static void main(String[] args) {
Account account = new Account(100 , "结婚基金");
drawManey you = new drawManey(account , 50 , "你");
drawManey Girfriend = new drawManey(account , 100 , "女朋友");
you.start();
Girfriend.start();
}
}
class Account{
int maney;
String name;
public Account(int maney, String name) {
this.maney = maney;
this.name = name;
}
}
class drawManey extends Thread{
Account account;
int drawingMoney;// 设置取的钱
int nowMoney;// 设置现在手里的钱
public drawManey(Account account , int drawingMoney , String name){
super(name);
this.drawingMoney = drawingMoney;
this.account = account;
}
public void run(){
if(account.maney < drawingMoney){
System.out.println(Thread.currentThread().getName() + "没钱了 , 无法取出!");
}
try {
sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
account.maney = account.maney - drawingMoney;//卡内余额
nowMoney = nowMoney + drawingMoney;//手上的钱
System.out.println(account.name + "的卡余额为" + account.maney);
// Thread.currentThread().getName() = this.getName();
System.out.println(this.getName() + "手上的钱为" + nowMoney);
}
}
线程集合
import java.util.ArrayList;
public class UnsafeDemo3 {
public static void main(String[] args) throws InterruptedException {
ArrayList<String> string = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{string.add(Thread.currentThread().getName());}).start();
}
Thread.sleep(1000);
System.out.println(string.size());
}
}
同步方法及同步块
同步方法
//安全的买票
//线程不安全,有负数
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket station = new BuyTicket();
Thread t1 = new Thread(station,"我");
Thread t2 = new Thread(station,"你");
Thread t3 = new Thread(station,"他");
t1.start();
t2.start();
t3.start();
}
}
class BuyTicket implements Runnable{
//买票
private int ticketNums =10;
boolean flag=true;//外部停止方式
@Override
public void run() {
//买票
while(flag){
try {
buy();
} catch (Exception e) {
e.printStackTrace();
}
}
}
//synchronized 同步方法,锁的是this
private synchronized void buy(){
//判断是否有票
if(ticketNums<=0){
flag=false;
return;
}
//模拟延时
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//买票
System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
}
同步块
//不安全的取钱
//两个人去银行取钱,账户
public class UnsafeBank {
public static void main(String[] args) {
//账户
Account account = new Account(100,"结婚基金");
Drawing you = new Drawing(account,50,"你");
Drawing girlfriend = new Drawing(account,100,"grilfriend");
you.start();
girlfriend.start();
}
}
//账户
class Account{
int money; //余额
String name; //卡名
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
//银行:模拟取款
class Drawing extends Thread{
Account account;//账户
//取了多少钱
int drawingMoney;
//现在手里有多少钱
int nowMoney;
//构造方法
public Drawing(Account account,int drawingMoney,String name ){
super(name);
this.account=account;
this.drawingMoney=drawingMoney;
}
//取钱的操作
//synchronized默认锁的是this
@Override
public void run() {
//锁的对象就是变化的量,需要增删改的对象
synchronized (account) {
//判断有没有钱
if (account.money - drawingMoney < 0) {
System.out.println(Thread.currentThread().getName() + "钱不够,取不了");
return;
}
//sleep可以放大问题的发生性
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//卡内余额=余额-你取的钱
account.money = account.money - drawingMoney;
//你手里的钱
nowMoney = nowMoney + drawingMoney;
System.out.println(account.name + "余额为:" + account.money);
//Thread.currentThread().getName()=this.getName(),this指代继承的Thread类。
System.out.println(this.getName() + "手里的钱:" + nowMoney);
}
}
}
JUC安全集合(拓展)
import java.util.concurrent.CopyOnWriteArrayList;
import static java.lang.Thread.sleep;
public class CopyWriteon {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
//本身就为安全的集合 看源码可以知道 private transient volatile Object[] array;
//transient 有序的 volatie 唯一的
for (int i = 0; i < 1000; i++) {
list.add(Thread.currentThread().getName());
}
try {
sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(list.size());
}
}
死锁
public class Deadlock {
public static void main(String[] args) {
Makeup makeup = new Makeup(0 , "灰姑娘");
Makeup makeup1 = new Makeup(1 , "白雪公主");
makeup.start();
makeup1.start();
}
}
class Lipstick{
//口红
}
class Mirror{
//镜子
}
class Makeup extends Thread{
static final Lipstick lipstick = new Lipstick();
static final Mirror mirror = new Mirror();
int choice;
String girlName;
public Makeup(int choice , String girlName){
this.choice = choice;
this.girlName = girlName;
}
@Override
public void run() {
//化妆
Makeup();
}
//拿完口红的锁放口袋里面又拿镜子 是拿不到的
private void Makeup(){
if(choice == 0){
synchronized (lipstick){
System.out.println(this.girlName + "拿到了口红!");
synchronized (mirror){
System.out.println(this.girlName + "拿了镜子!");
}
}
}
else{
synchronized (mirror){
System.out.println(this.girlName + "拿了镜子!");
synchronized (lipstick){
System.out.println(this.girlName + "拿到了口红!");
}
}
}
}
}
解决方案
//拿完口红的锁再放回去,再拿 可以拿到
private void Makeup(){
if(choice == 0){
synchronized (lipstick){
System.out.println(this.girlName + "拿到了口红!");
}
synchronized (mirror){
System.out.println(this.girlName + "拿了镜子!");
}
}
else{
synchronized (mirror){
System.out.println(this.girlName + "拿了镜子!");
}
synchronized (lipstick){
System.out.println(this.girlName + "拿到了口红!");
}
}
}
Lock显式锁
实例
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.Thread.sleep;
public class LockDemo {
public static void main(String[] args) {
TestLock testLock = new TestLock();
new Thread(testLock).start();
new Thread(testLock).start();
new Thread(testLock).start();
}
}
class TestLock implements Runnable{
int TicketNumber = 10;
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
if (TicketNumber > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(TicketNumber--);
} else {
break;
}
}
}
}
使用lock锁
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.Thread.sleep;
public class LockDemo {
public static void main(String[] args) {
TestLock testLock = new TestLock();
new Thread(testLock).start();
new Thread(testLock).start();
new Thread(testLock).start();
}
}
class TestLock implements Runnable{
int TicketNumber = 10;
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
lock.lock();
try {
if (TicketNumber > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(TicketNumber--);
} else {
break;
}
}finally {//如果同步代码有异常,要将unlock()写入finally
lock.unlock();
}
}
}
}
管程法
public class ProductorD {
public static void main(String[] args) {
synContainer Container = new synContainer();
new Productor(Container).start();
new Consumer(Container).start();
}
}
//生产者
class Productor extends Thread{
private final synContainer container;
Productor(synContainer container) {
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("生产了" + i + "只鸡");
container.push(new Chicken(i));
}
}
}
//消费者
class Consumer extends Thread{
private final synContainer container;
Consumer(synContainer container) {
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("我买了" + container.pop().number + "只鸡");
}
}
}
//产品
class Chicken{
int number;
public Chicken(int number){
this.number = number;
}
}
//缓冲区
class synContainer{
//需要一个容器的大小
Chicken[] chickens = new Chicken[10];
int count = 0;
//生产者放入产品
public synchronized void push(Chicken chicken){
//如果容器满了,就等待消费者消费
if(count == chickens.length){
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//通知消费者等待
}
//如果没有满,就需要丢入产品
chickens[count] = chicken;
count++;
//可以通知消费者消费
this.notify();
}
public synchronized Chicken pop(){
//判断能否消费
if(count == 0){
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//等待生产者生产,消费者等待
}
//如果可以消费
count--;
Chicken chicken = chickens[count];
//吃完了,通知生产者生产
this.notify();
return chicken;
}
}
信号灯法
public class ProductD {
public static void main(String[] args) {
TV tv = new TV();
new Player(tv).start();
new Watcher(tv).start();
}
}
//表演者
class Player extends Thread{
TV tv;
public Player(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if(i % 2 == 0){
this.tv.performer("ababa");
}else{
this.tv.performer("babab");
}
}
}
}
//观看者
class Watcher extends Thread{
TV tv;
public Watcher(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
tv.watch();
}
}
}
//产品
class TV{
//演员表演 , 观众等待 T
//观众观看 , 演员等待 F
String voice;
boolean flag = true;
//表演
public synchronized void performer(String voice){
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("演员表演了" + voice);
this.notify();
this.voice = voice;
this.flag = !this.flag;
}
//观看
public synchronized void watch(){
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("观看了" + voice);
this.notify();
this.flag = !this.flag;
}
}
线程池法
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Testpool {
public static void main(String[] args) {
//创建服务 , 创建线程池
//newFixedThreadPool 参数为线程池大小
ExecutorService service = Executors.newFixedThreadPool(10);
//执行
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
//关闭链接
service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() );
}
}

浙公网安备 33010602011771号