程序: 是指令和数据的有序集合, 本身没任何的含义,是一个静态概念
进程: 是执行程序的一次执行过程 一个动态概念
线程 : 一个进程可以有多个线程,当然至少有一个线程,否则无意义,线程是CPU执行和调度的单位
-
继承Thread类
-
实现Runnable接口
/**
* @ClassName: TestThread
* @Description:
* @Author
* @Date 2022/4/25
* @Version 1.0
*/
public class TestThread extends Thread{
@Override
public void run() {
for (int i = 0; i<200; i++) {
System.out.println(currentThread().getName() + "我在看代码------------------" + i );
}
}
public static void main(String[] args) {
TestThread testThread = new TestThread();
testThread.start();
for (int i = 0; i < 100; i++) {
System.out.println(currentThread().getName()+"在学习多线程---" + i);
}
}
}
2.实现Runnable接口创建线程
package com.kuang.demo1;
/**
* @ClassName: TestRunnable
* @Description:
* @Author
* @Date 2022/4/26
* @Version 1.0
*/
public class TestRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i<200; i++) {
System.out.println( "我在看代码------------------" + i );
}
}
public static void main(String[] args) {
TestRunnable testRunnable = new TestRunnable();
new Thread(testRunnable).start();
for (int i = 0; i < 100; i++) {
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println("在学习多线程---" + i);
}
}
}
3.总结
-
继承Thread类
- 子类继承Thread类具备多线程能力
- 启动线程 子类对象.start()
-
实现Runnable接口 推荐使用
-
实现Runnable具备多线程能力
-
启动线程: 传入目标对象+ Thread对象.start()
-
tip:还有一种创建线程方式 了解即可
public class TestCallable implements Callable<Boolean> {
private String url;
private String name;
public TestCallable(String url, String name) {
this.url = url;
this.name = name;
}
// 下载图片线程的执行体
@Override
public Boolean call() {
WebDownLLoader webDownLLoader = new WebDownLLoader();
webDownLLoader.downLoad(url, name);
System.out.println("下载了文件名为:" + name);
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
TestCallable t1 = new TestCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2F1114%2F0G520141919%2F200G5141919-2-1200.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=47d43ca821a757183016d42c33ec8b41", "1.jpg");
TestCallable t2 = new TestCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fclubimg.club.vmall.com%2Fdata%2Fattachment%2Fforum%2F202004%2F28%2F232538icfogvlsgjywjw36.jpg&refer=http%3A%2F%2Fclubimg.club.vmall.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=0b38b8beab9576e4a06f51f6c81c70a5", "2.jpg");
TestCallable t3 = new TestCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201603%2F04%2F20160304192803_HRdrS.thumb.700_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660908&t=1a2a2fb9358036ee12f43e25b1e3564f", "3.jpg");
// 创建执行服务
ExecutorService service = Executors.newFixedThreadPool(3);
// 提交执行
Future<Boolean> r1 = service.submit(t1);
Future<Boolean> r2 = service.submit(t2);
Future<Boolean> r3 = service.submit(t3);
boolean res1 = r1.get();
boolean res2 = r1.get();
boolean res3 = r1.get();
System.out.println(res1);
System.out.println(res2);
System.out.println(res3);
// 关闭服务
service.shutdown();
}
//下载器
class WebDownLLoader {
// 下载方法
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异常");
}
}
}
}
三、静态代理模式
package com.kuang.demo1;
/**
* @ClassName: StaticProxy
* @Description: 静态代理
* @Author
* @Date 2022/4/26
* @Version 1.0
*/
/**
* 静态代理模式总结
* 真实对象和代理对象都要实现同一个接口
* 代理角色要代理真实角色
* 好处
* 代理对象可以做真实对象做不了的事情
* 真实对象专注做自己的事情
* */
public class StaticProxy {
public static void main(String[] args) {
new Thread(()-> System.out.println("我爱你")).start();
// 是不是一样,线程底部就用了静态代理模式
new WeddingCompany(new You()).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 after() {
System.out.println("结婚之后,收尾款");
}
private void before() {
System.out.println("结婚之前,布置现场");
}
}
四、lamda表达式
1.含义
-
希腊字母第十一位字母
-
避免匿名内部类定义过多
-
属于函数式编程概念
避免内部类过多
代码更加简洁
只留核心代码 去掉无意义代码
理解函数式接口是关键
函数式接口定义:
-
任何接口都只有一个抽象方法,那么他就是一个函数式接口
-
函数接口可以用lamda简化
package com.kuang.demo1;
/**
* @ClassName: TestLamda
* @Description:
* @Author
* @Date 2022/4/26
* @Version 1.0
*/
public class TestLamda {
public static void main(String[] args) {
// //1.普通方式
// Like like = new Like();
// like.Lambda();
// //2.局部类部类
// class Like3 implements ILike {
// @Override
// public void Lambda() {
// System.out.println("I like yan3");
// }
// }
// ILike like=new Like3();
// like.Lambda();
// }
// //3.匿名内部类
// ILike like = null;
// like = new ILike() {
// @Override
// public void Lambda() {
// System.out.println("I like yan4");
// }
// };
// like.Lambda();
//4.用lambda简化
ILike like = null;
like = () ->System.out.println("I like yan5");
like.Lambda();
}
}
//1.定义一个接口
interface ILike{
void Lambda();
}
//2.定义一个实现类
class Like implements ILike{
@Override
public void Lambda() {
System.out.println("I like yan");
}
}
五、线程状态
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 (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("=============");
});
//观察状态
Thread.State state = thread.getState();
System.out.println(state);
System.out.println("#########");
//观察启动后
thread.start(); //启动线程
state=thread.getState();
System.out.println(state); //运行
while (state!=Thread.State.TERMINATED){
Thread.sleep(1000);
state=thread.getState(); //更新线程状态
System.out.println(state); //输出状态
}
}
}
六、线程的优先级
七、守护线程
概念
代码测试:
package com.kuang.demo1;
public class TestDaemon {
public static void main(String[] args) {
Ysou you = new Ysou();
God god = new God();
Thread thread = new Thread(god);
thread.setDaemon(true); //默认flase 表示守护线程
thread.start(); //上帝,守护线程启动
new Thread(you).start(); //你 用户线程启动
}
}
class Ysou implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("你在开心的活着第"+i+"天");
}
System.out.println("===拜拜,我要去另外一个世界了===");
}
}
class God implements Runnable {
@Override
public void run() {
int i = 0;
while (true) {
System.out.println("神圣在保佑我" + i++);
}
}
}
八、线程同步
1.概念:
2.方式
-
同步方法
-
同步代码块
synchronized同步方法
package com.kuang.demo1;
/**
* @ClassName: SafeBuyTicket
* @Description:
* @Author
* @Date 2022/4/26
* @Version 1.0
*/
public class SafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket=new BuyTicket();
new Thread(buyTicket,"苦逼的我").start();
new Thread(buyTicket,"牛逼的你们").start();
new Thread(buyTicket,"荒天帝").start();
}
}
class BuyTicket implements Runnable {
// 10张票
private int ticketNum = 10;
// 标注
boolean flag = true;
@Override
public void run() {
while(flag) {
try{
buy();
}catch (Exception e) {
e.printStackTrace();
}
}
}
public synchronized void buy() throws InterruptedException {
if (ticketNum <= 0) {
flag = false;
return;
}
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"买了第"+ticketNum--+"张票");
}
}
synchronized 代码块方法
package com.kuang.demo1;
/**
* @ClassName: SafeBank
* @Description: 俩个线程 *** 作一个对象
* @Author
* @Date 2022/4/26
* @Version 1.0
*/
public class SafeBank {
public static void main(String[] args) {
Account account = new Account(1000,"结婚钱");
new Drawing(account,50,"你").start();
new Drawing(account,100,"你老婆").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() {
synchronized (account) {
//判断有没有钱
if (account.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money=account.money-drawingMoney; //卡内余额=余额-取的钱
nowMoney=drawingMoney+nowMoney; //手里的钱=取的钱+原来手里的钱
System.out.println(account.name+"当前的余额为:"+account.money);
// System.out.println(Thread.currentThread().getName()+"手里的钱:"+nowMoney);
System.out.println(this.getName()+"手里的钱:"+nowMoney);
}
}
}
九、死锁
1.死锁的条件以及解决办法
十、Lock锁
可重入锁
可重入锁 ReentrantLock()package com.kuang.demo1;
import java.util.concurrent.locks.ReentrantLock;
/**
* @ClassName: ReentrantLock
* @Description:
* @Author
* @Date 2022/4/26
* @Version 1.0
*/
public class TestReentrantLock {
public static void main(String[] args) {
TestLock02 testLock02 = new TestLock02();
new Thread(testLock02).start();
new Thread(testLock02).start();
new Thread(testLock02).start();
}
}
class TestLock02 implements Runnable{
int ticketNums=1000;
//定义ReentrantLock
private final ReentrantLock lock = new ReentrantLock ();
@Override
public void run() {
while (true){
try{
lock.lock(); //加锁
if (ticketNums>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-->"+ticketNums--);
}
else {
break;
}
}finally {
lock.unlock(); //解锁
}
}
}
}
Lock锁和syncronized对比
对比
十一、线程协作
线程通信
线程通信分析
解决办法
- 管程法---- 利用缓冲区
//测试:生产者消费者模型 ,利用缓冲区解决:管程法
//生产者,消费者,长跑,缓冲区
public class TestPC {
public static void main(String[] args) {
SynContainer c = new SynContainer();
new Producer(c).start();
new Consumer(c).start();
}
}
//生产者
class Producer extends Thread{
SynContainer container;
public Producer(SynContainer container) {
this.container = container;
}
//生产
@Override
public void run() {
for(int i=1;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=1;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)
{
//如果容器满了,就需要等待消费者消费
if(count == chickens.length)
{
//通知消费者消费,生产等待
try {
this.wait();
}catch(Exception e) {
e.printStackTrace();
}
}
//如果没有满,我们就需要丢入产品
chickens[count] = chicken;
count++;
//可以通知消费者了
this.notifyAll();
}
//消费者消费产品
public synchronized Chicken pop() {
//判断能否消费
if(count==0)
{
//等待生产者生产,消费者等待
try {
this.wait();
}catch(Exception e)
{
e.printStackTrace();
}
}
//如果可以消费
count--;
Chicken chicken = chickens[count];
//吃完了,通知生产者生产
this.notifyAll();
return chicken;
}
}
- 信号灯法----利用标志位
//测试生产消费者问题2,信号灯法,标志位解决
public class TestPC2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
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.play("完美世界");
}
else
{
this.tv.play("快来bibi看狂神");
}
}
}
}
//消费者-》观众
class Watcher extends Thread{
TV tv;
public Watcher(TV tv)
{
this.tv = tv;
}
@Override
public void run() {
for(int i=0;i<20;i++)
{
tv.watch();
}
}
}
//产品-》节目
class TV {
//演员录制,观众等待
//观众观看,演员等待
String voice;//表演的节目
boolean flag = true;
//录制
public synchronized void play(String voice) {
if(!flag)
{
try {
this.wait();
}catch(Exception e)
{
e.printStackTrace();
}
}
System.out.println("演员录制了"+voice);
//通知观众观看
this.notifyAll();
this.voice = voice;
this.flag = !this.flag;
}
//观众看
public synchronized void watch() {
if(flag)
{
try {
this.wait();
}catch(Exception e)
{
e.printStackTrace();
}
}
System.out.println("观看了"+voice);
//通知演员录制
this.notifyAll();
this.flag = !this.flag;
}
}
十二、线程池
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AWnovN3S-1650966393406)(C:\Users\jiangshang\AppData\Roaming\Typora\typora-user-images\image-20220426173406146.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RZHgDIVO-1650966393407)(C:\Users\jiangshang\AppData\Roaming\Typora\typora-user-images\image-20220426173430054.png)]
ExecutorService和Executorspackage TestLambda;
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 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());
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)