java基础 线程理解
来源:互联网 发布:淘宝首页装修视频教程 编辑:程序博客网 时间:2024/04/30 00:44
线程类:Thread类,Runnable类,我们一般定义一个线程有两种方式一种是自定义一个类继承Thread类我们自己扩张run方法,然后生成我们自定义的类的对象。调用start方法启动该线程。另外一种是,我们我们实现Runnable类,扩张其run方法然后生成自定义的类的对象,将其作为Thread类的构造方法的参数,生成Thread对象然后调用生成的类的start方法。
实现:
①.
package com.itheima.study.thread;
//扩张Thread类
public class MyThread extends Thread
{
@Override
public void run()
{
super.run();
for(int i = 0; i < 5; i++)
{
System.out.println("Thread " + i);
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
②.
package com.itheima.study.thread;
//实现Runnbale类
public class MyRunnable implements Runnable
{
@Override
public void run()
{
for(int i = 5; i > 0; i--)
{
System.out.println("Runnable " + i);
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
③.
//测试类
package com.itheima.study.thread;
public class Test
{
public static void main(String[] args)
{
Thread thread1 = new MyThread();
Thread thread2 = new Thread(new MyRunnable());
thread1.start();
thread2.start();
}
}
运行结果:
Thread 0
Runnable 5
Runnable 4
Thread 1
Thread 2
Runnable 3
Thread 3
Runnable 2
Thread 4
Runnable 1
了解了基本的定义和启动一个线程了,以一个经典案列来体现线程。银行卡取钱,取一次钱后,必须存钱。
这其实是一个生产者消费者模式:把银行账户比作一个工厂,当工厂生产了食物过后,消费者必须吃掉食物。然后工厂发现没有食物存在了,又继续生产。一旦有食物存在,工厂就不会继续生产而是等待消费者消费。
Account类:账户类,提供存钱取钱的方法。
FetchMoney类:取钱线程类;操作Account类中的取钱方法。
SaveMoney类:存钱线程类;操作Account类中的存钱方法。
Client类:启动线程。
①.
package com.itheima.study.producer.customer;
//定义银行账户类
public class Account
{
//银行卡余额
private double balance;
// true 表示没有存钱 false则表示已经存钱
private boolean Empty = Boolean.TRUE;
//判断账户是否有余额
public boolean isEmpty()
{
return Empty;
}
//设置账户余额情况,当存钱或者取钱过后,账户余额情况应该有相应的变化
public void setEmpty(boolean empty)
{
Empty = empty;
}
//初始化账户余额
public Account(double balance)
{
super();
this.balance = balance;
}
//得到账户具体的余额
public double getBalance()
{
return balance;
}
//设置账户的余额,取钱或者存钱过后账户余额都应该减少或者增加
public void setBalance(double balance)
{
this.balance = balance;
}
//操作存钱的方法
public void save(double num)
{
//由于取钱和存钱不能同时发生,防止并发所以要用synchronized关键字修饰
//就是将当前有类加载器加到到虚拟机中的字节码类(Class类)上锁
//class类只有唯一一份,所以就防止了存钱和取钱操作同时被调用
synchronized (Account.class)
{
//如果账户中存在钱
if (!this.Empty)
{
try
{
//让调用该方法的线程处于处于等待状态,去执行取款线程
Account.class.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
//当取款线程执行完成后,执行了Account.class.notify();就将当前的在监视器上等待的线程唤醒,就会执行当前线程下面的代码
// 存款操作
System.out.println(Thread.currentThread().getName() + " 存款前金额为 : " + this.getBalance() + " 本次存款 : " + num);
//存钱过后账户余额增加
this.setBalance(this.getBalance() + num);
System.out.println("存款后金额为 : " + this.getBalance());
System.out.println();
//表示卡上已经有钱
this.Empty = false;
//唤醒取款线程
Account.class.notify();
}
}
public void fetch(double num)
{
//这里的眼里其实就是雨存钱相反。
// 在取款的时候如果发现还没有存款,那么取款的线程等待, 让存款的线程执行
synchronized (Account.class)
{
if (this.Empty)
{
try
{
Account.class.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
//另一个线程执行了Account.class.notify();后就唤醒了当前在等待的线程继续执行wait之后的代码
// 取款操作
//如果卡上余额大于取款金额
if (this.getBalance() >= num)
{
System.out.println(Thread.currentThread().getName() + " 取款前金额为 : " + this.getBalance() + " 本次取款 : " + num);
//账户余额减少
this.setBalance(this.getBalance() - num);
System.out.println("取款后金额为 : " + this.getBalance());
}
else
{
//取款金额大于卡上余额
System.out.println(Thread.currentThread().getName()+ "亲,余额不足 当前余额 : " + this.getBalance() + " 本次取款 : " + num);
}
System.out.println();
//取款后标记为卡上没钱
this.Empty = true;
//唤醒存款线程
Account.class.notify();
}
}
}
②.
package com.itheima.study.producer.customer;
// 取款线程
public class FetchMoney extends Thread
{
//持有一个Account类型的引用
private Account account;
//每次取款的数量
private double number;
//初始化account,number
//name修改线程名字
public FetchMoney(Account account, double number, String name)
{
super(name);
this.account = account;
this.number = number;
}
@Override
public void run()
{
//要执行取款的次数,取款过后线程wait就会执行存款。
for (int i = 0; i < 5; i++)
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
account.fetch(number);
}
}
}
③.
package com.itheima.study.producer.customer;
// 存款线程
public class SaveMoney extends Thread
{
//持有一个对Account类型的引用
private Account account;
//存钱的数目
private double number;
//初始化accout(初始化为与取款线程中的Account指向同一个地址的引用),number;
//name为修改线程名字
public SaveMoney(Account account, double number, String name)
{
super(name);
this.account = account;
this.number = number;
}
@Override
public void run()
{
//存款的次数,存款过后,wait执行取款
for (int i = 0; i < 5; i++)
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
account.save(number);
}
}
}
④.
package com.itheima.study.producer.customer;
public class Client {
public static void main(String[] args) {
Account a = new Account(0);
SaveMoney saveMoney = new SaveMoney(a, 900, "存钱:");
FetchMoney fetchMoney = new FetchMoney(a, 800, "取钱:");
saveMoney.start();
fetchMoney.start();
}
}
运行结果:
存钱: 存款前金额为 : 0.0 本次存款 : 900.0
存款后金额为 : 900.0
取钱: 取款前金额为 : 900.0 本次取款 : 800.0
取款后金额为 : 100.0
存钱: 存款前金额为 : 100.0 本次存款 : 900.0
存款后金额为 : 1000.0
取钱: 取款前金额为 : 1000.0 本次取款 : 800.0
取款后金额为 : 200.0
存钱: 存款前金额为 : 200.0 本次存款 : 900.0
存款后金额为 : 1100.0
取钱: 取款前金额为 : 1100.0 本次取款 : 800.0
取款后金额为 : 300.0
存钱: 存款前金额为 : 300.0 本次存款 : 900.0
存款后金额为 : 1200.0
取钱: 取款前金额为 : 1200.0 本次取款 : 800.0
取款后金额为 : 400.0
存钱: 存款前金额为 : 400.0 本次存款 : 900.0
存款后金额为 : 1300.0
取钱: 取款前金额为 : 1300.0 本次取款 : 800.0
取款后金额为 : 500.0
- java基础 线程理解
- Java基础之多线程的理解
- Java基础——深入理解Java线程池
- 进程,线程基础理解
- Java基础之——线程通信的理解
- java线程安全理解
- java线程理解
- java线程安全理解
- java线程安全理解
- java线程的理解
- java线程池理解
- java线程安全理解
- java线程优先级理解
- java线程安全理解
- Java线程理解
- 理解java线程状态
- Java线程池理解
- java守护线程理解
- 苹果更新App Store审核指南
- hdu 4474 Yet Another Multiple Problem (余数判重 + BFS)
- 杭电 1870 愚人节的礼物
- iOS 数据持久化
- iOS面试题(三)
- java基础 线程理解
- boost typeof
- SQL 已更新或删除的行值要么不能使该行成为唯一行(sqlserver中有多行所有的列重复的数据,无法更新或删除问题)
- boost noncopyable
- Macbook中的文件显示与隐藏方法
- poj 1065做题笔记
- matlab基本画图
- Java中的Heap和Stack
- html输入框只能输入数字