线程、进程、多线程
普通方法和调用多线程
线程创建
三种创建方式
Thread
总结:线程开启不一定立即执行,CPU安排调度
package TestThread;
//创建线程的方式之一:继承Thread类,重新run方法,调用start开启线程
public class demo01 extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("run------" + i);
}
}
public static void main(String[] args) {
demo01 demo01 = new demo01();
demo01.start();
for (int i = 0; i < 20; i++) {
System.out.println("main++++++++" + i);
}
}
}
网图下载
package TestThread.domo01;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
public class TestThread01 extends Thread{
private String url;
private String name;
public TestThread01(String url, String name){
this.url = url;
this.name = name;
}
@Override
public void run() {//下载图片的执行体
WebDownloader webDownloader = new WebDownloader();
webDownloader.download(url, name);
System.out.println("下载了文件名为:" + name);
}
public static void main(String[] args) {
TestThread01 t1 = new TestThread01("https://src.sjt2f-1575-481c-ae36-00d5e214b435-U6EBAm04.png", "1.png");
TestThread01 t2 = new TestThread01("https://srca0-81d9-b213259aa625-FcxWZ75r.png", "2.png");
TestThread01 t3 = new TestThread01("https://src.a4c76a-17ab-4dbe-a0d7-85e6fa7c795d-p9ArBtQD.png", "3.png");
t1.start();
t2.start();
t3.start();
}
}
class WebDownloader {
public void download(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url), new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("io异常,Downloader方法出现异常");
}
}
}
实现Runnable接口
package TestThread.domo01;
//创建线程方式2:实现Runnable接口,重写run方法,执行线程需要丢入runnable接口实现类。调用start方法。
public class TestThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("run------" + i);
}
}
public static void main(String[] args) {
TestThread testThread = new TestThread();
//Thread thread = new Thread(testThread);
//thread.start();
new Thread(testThread).start();
for (int i = 0; i < 20; i++) {
System.out.println("main++++++++" + i);
}
}
}
小结
初识并发问题
package TestThread.demo02;
public class TestThread01 implements Runnable{
private int piao = 10;
@Override
public void run() {
while (true){
if(piao<=0){
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "--->拿到了第" + piao-- + "票");
}
}
public static void main(String[] args) {
TestThread01 testThread01 = new TestThread01();
new Thread(testThread01,"小米").start();
new Thread(testThread01,"小明").start();
new Thread(testThread01,"小天").start();
}
}
龟兔赛跑
package TestThread.demo02;
public class Race implements Runnable{
private static String winner;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + "---》跑了" + i + "步");
//如果比赛结束了,就停止程序
if (flag(i)){
break;
}
}
}
//判断是否完成比赛
public boolean flag(int step){
if (winner !=null){
return true;
}{
if (step == 100){
winner = Thread.currentThread().getName();
System.out.println("winner is " + winner);
}
return false;
}
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race,"兔子").start();
new Thread(race, "乌龟").start();
}
}
Lamda表达式
Lamdba表达式
演化过程…(?)
package lambda;
public class TestLamda01 {
//3.静态内部类
static class like2 implements Ilike{
@Override
public void lambda() {
System.out.println(" i like lambda2");
}
}
public static void main(String[] args) {
like like = new like();
like.lambda();
like2 like2 = new like2();
like2.lambda();
//4.局部内部类
class like3 implements Ilike{
@Override
public void lambda() {
System.out.println(" i like lambda3");
}
}
like3 like3 = new like3();
like3.lambda();
//5.匿名内部类,没有类的名称,必须借助接口或者父类
Ilike like4 = new Ilike(){
@Override
public void lambda() {
System.out.println(" i like lambda4");
}
};
like4.lambda();
//6.用lambda简化
Ilike like5 = ()->{
System.out.println(" i like lambda5");
};
like5.lambda();
}
}
//定义一个函数式接口
interface Ilike {
void lambda();
}
//实现类
class like implements Ilike{
@Override
public void lambda() {
System.out.println(" i like lambda");
}
}
package lambda;
public class TestLambda02 {
public static void main(String[] args) {
//lambda表示简化
ILove love = (int a)->{
System.out.println("love--->" + a);
};
//简化1:参数类型
love = (a)->{
System.out.println("love--->" + a);
};
//简化2:括号
love = a->{
System.out.println("love--->" + a);
};
//简化3:去掉花括号
love = a -> System.out.println("love--->" + a);
love.love(520);
}
}
interface ILove{
void love(int a);
}
静态代理模式
package lambda;
public class StaticProxy {
public static void main(String[] args) {
WeddingCompany weddingCompany = new WeddingCompany(new You());
weddingCompany.HappyMarry();
}
}
interface Marry{
void HappyMarry();
}
//真实角色,你去结婚
class You implements Marry{
@Override
public void HappyMarry() {
System.out.println("Tom 要结婚了");
}
}
//代理角色,帮助你结婚
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("结婚之后,收尾款");
}
}
线程停止
线程状态
线程方法
停止线程
package state;
public class TestStop implements Runnable{
//1.设置一个标志位
private boolean flag = true;
@Override
public void run() {
int i = 0;
while (flag) {
System.out.println("run....Thread.." + i++);
}
}
//设置一个公开的方法停止线程,转换标志位
public void stop(){
this.flag = false;
}
public static void main(String[] args) {
TestStop testStop = new TestStop();
new Thread(testStop).start();
for (int i = 0; i < 1000; i++) {
System.out.println("main.." + i);
if (i == 90){
//调用stop方法切换标志位,让线程停止
testStop.stop();
System.out.println("线程该停止了...");
}
}
}
}
线程休眠_sleep
线程休眠
模拟网络延时:放大问题的发生性
package state;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestSleep02 {
public static void main(String[] args) {
Date Starttime = new Date(System.currentTimeMillis());//获取系统时间
while (true){
try {
Thread.sleep(1000);//延时1秒
System.out.println(new SimpleDateFormat("HH:mm:ss").format(Starttime));
Starttime = new Date(System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程礼让_yield
package state;
public class TestYield {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield,"小米").start();
//new Thread(myYield,"小马").start();
//new Thread(myYield,"小明").start();
//new Thread(myYield,"小花").start();
new Thread(myYield,"小萨").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "--->进程开始执行...");
Thread.yield();
System.out.println(Thread.currentThread().getName() + "--->进程结束执行...");
}
}
线程强制执行_join
package state;
//测试join方法,想象为插队
public class TestJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("线程VIP---->" + 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 < 500; i++) {
if (i == 200){
thread.join();//插队
System.out.println("main" + i);
}
}
}
}
观测线程状态
package state;
public class TestState {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("/");
}
});
//观察状态
Thread.State state = thread.getState();
System.out.println(state);
//观察启动后
thread.start();
state = thread.getState();
System.out.println(state);
//只要线程不终止,就一直输出状态
while (state != Thread.State.TERMINATED) {
Thread.sleep(100);
state = thread.getState();//更新线程状态
System.out.println(state);//输出线程状态
}
}
}
线程优先级
package state;
//测试线程优先级
public class TestPriority {
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);
//先设置优先级,再启动
t1.start();
t2.setPriority(1);
t2.start();
t3.setPriority(4);
t3.start();
t4.setPriority(Thread.MAX_PRIORITY);//MAX_PRIORITY=10
t4.start();
// t5.setPriority(-1);
// t5.start();
//
// t6.setPriority(11);
// t6.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+ "--->" + Thread.currentThread().getPriority());
}
}
守护(deamon)线程
package state;
public class TestDeamon {
public static void main(String[] args) {
God god = new God();
You you = new You();
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 You implements Runnable{
public void run(){
for (int i = 0; i < 36500; i++) {
System.out.println("你一生都开心的活着");
}
System.out.println("-=======goodbye world....");
}
}
就是按理说god线程是不会停止的,但是把它变为守护线程之后呢,虚拟机就不管它了,都是围绕着用户进程的(是吧?)
线程同步机制
并发
线程同步
三大不安全案例
线程不安全案例1:不安全的买票
package cn.bloghut.syn;
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket station = new BuyTicket();
new Thread(station,"闲言").start();
new Thread(station,"鸡哥").start();
new Thread(station,"黄牛").start();
}
}
class BuyTicket implements Runnable {
//票
private int ticketNums = 10;
private boolean flag = true;//外部停止方式
@Override
public void run() {
//买票
while (flag) {
buy();
}
}
private void buy() {
//判断是否有票
if (ticketNums <= 0) {
flag = false;
return;
}
//模拟延时
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//买票
System.out.println(Thread.currentThread().getName() + "拿到" + ticketNums-- + "张票");
}
}
线程不安全案例2:不安全的取钱
package cn.bloghut.syn;
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,"girlFriend");
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;
}
@Override
public void run() {
//判断有没有钱
if (account.money - drawingMoney < 0) {
System.out.println(Thread.currentThread().getName() + "钱不够,取不了");
return;
}
try {
Thread.sleep(100);
} 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();
System.out.println(this.getName() + "手里的钱" + nowMoney);
}
}
线程不安全案例3:不安全的集合
package cn.bloghut.syn;
import java.util.ArrayList;
import java.util.List;
public class UnsafeList {
public static void main(String[] args) throws InterruptedException {
List<String> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
Thread.sleep(3000);
System.out.println(list.size());
}
}
同步方法和同步块
同步方法
同步方法弊端
同步块
CopyOnWriteArrayList
juc安全类型的集合
死锁
死锁示例:
package syn;
import com.sun.org.apache.bcel.internal.generic.NEW;
public class DeadLock {
public static void main(String[] args) {
Makeup hg = new Makeup(0, "灰姑凉");
Makeup bx = new Makeup(1, "白雪公主");
new Thread(hg).start();
new Thread(bx).start();
}
}
class Lipstick{ //口红
}
class Mirror{//镜子
}
class Makeup implements Runnable{
//需要的资源只有一份,用static来保证一份
static Lipstick lipstick = new Lipstick();
static Mirror mirror =new Mirror();
int choice;//选择
String name;//选择化妆品的女孩
public Makeup(int choice, String name) {
this.choice = choice;
this.name = name;
}
@Override
public void run() {
//化妆
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//化妆的方法,互相持有对方的锁,需要拿到对方的资源
private void makeup() throws InterruptedException {
if (choice == 0){
synchronized (lipstick){
System.out.println(this.name + "获得了口红的锁");
Thread.sleep(1000);
//休息了一秒,想要获得镜子的锁
synchronized (mirror) {
System.out.println(this.name + "获得了镜子的锁");
}
}
}else {
synchronized (mirror){
System.out.println(this.name + "获得了镜子的锁");
Thread.sleep(2000);
//休息了一秒,想要获得口红的锁
synchronized (lipstick) {
System.out.println(this.name + "获得了口红的锁");
}
}
}
}
}
然后是把锁中锁拿到了锁外面,就可以解决了死锁问题,但是我特么觉得不合逻辑呀…
死锁避免方法
lock(锁)
ReentrantLock 可重入锁
package syn;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
public static void main(String[] args) {
TestLock2 t1 = new TestLock2();
new Thread(t1).start();
new Thread(t1).start();
new Thread(t1).start();
}
}
class TestLock2 implements Runnable{
int ticketNums = 10;
//定义lock锁
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true){
try {
lock.lock();//加锁
if (ticketNums > 0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(ticketNums--);
}else {
break;
}
} finally {
//解锁
lock.unlock();
}
}
}
}
synchronized 与 Lock 的对比
生产者消费者问题
线程通信
解决方式1
解决方式2
管程法
package syn;
//测试:生产者消费者模型---》利用缓存区解决:管程法
//生产者,消费者,产品,缓冲区
public class TestPC {
public static void main(String[] args) {
SynContainer container = new SynContainer();
new Productor(container).start();
new Consumer(container).start();
}
}
//生产者
class Productor extends Thread{
SynContainer container;
public Productor(SynContainer container){
this.container = container;
}
//生产、
@Override
public void run() {
for (int i = 0; i < 100; i++) {
container.push(new Chicken(i));
System.out.println("生产了" + i + "只鸡");
}
}
}
//消费者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container){
this.container = container;
}
//消费
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了----》" + container.pop().id + "只鸡");
}
}
}
//产品
class Chicken {
int id;//产品编号
public Chicken(int id) {
this.id = id;
}
}
//缓冲区
class SynContainer{
//需要一个容器的大小
Chicken[] chickens = new Chicken[10];
//容器计数器
int count = 0;
//生产者放入产品
public synchronized void push(Chicken chicken){
//如果容器满了,就需要等待消费者消费
while (count==chickens.length){
//通知消费者消费,生产等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果没有满,我们就需要丢入产品
chickens[count] = chicken;
count++;
//可以通知消费者消费
this.notifyAll();
}
//消费者消费产品
public synchronized Chicken pop(){
//判断能否消费
if (count==0){
//等待生产者生产,消费者等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果可以消费
count--;
Chicken chicken = chickens[count];
//吃完了,通知生产者生产
this.notifyAll();
return chicken;
}
}
信号灯法
package syn;
//测试:信号灯法,标志位解决
public class TestPC02 {
public static void main(String[] args) {
TV tv = new TV();
new Palyer(tv).start();
new Watcher(tv).start();
}
}
//生产者---演员
class Palyer extends Thread{
TV tv;
public Palyer(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if (i%2==0){
this.tv.paly("快乐大本营");
}else {
this.tv.paly("广告进行曲~~~");
}
}
}
}
//消费者---观众
class Watcher extends Thread{
TV tv;
public Watcher(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
this.tv.watch();
}
}
}
//产品----节目
class TV{
//演员表演,观众等待 T
//观众观看,演员等待 F
String voice;//
boolean flag = true;//
//表演
public synchronized void paly(String voice){
if (flag==false){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("演员表演了" + voice);
//通知观众观看
this.notifyAll();
this.voice = voice;
this.flag = !this.flag;
}
//观看
public synchronized void watch(){
if (flag==true){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("观众观看" + voice);
//通知演员表演
this.notifyAll();
this.flag = !this.flag;
}
}
//
线程池
使用线程池
package syn;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestPool {
public static void main(String[] args) {
//1.创建服务,创建线程池
ExecutorService service = Executors.newFixedThreadPool(10);
//执行
service.execute(new TPool());
service.execute(new TPool());
service.execute(new TPool());
service.execute(new TPool());
//2.关闭连接
service.shutdown();
}
}
class TPool implements Runnable{
@Override
public void run() {
for (int i = 0; i < 1; i++) {
System.out.println(i);
System.out.println(Thread.currentThread().getName() + i);
}
}
}