java:多线程(代理模式,Thread中的方法,Timer,生产者和消费者)
*进程:一个正在运行的程序,进程是操作系统分配资源的基本单位,每个进行有独立的内存空间,进程之间切换开销较大。
*线程:一个轻量级的进程,线程是任务调度的基本单位,一个进程可以有多个线程,
* 系统没有为线程分配额外的内存空间,一个进程中的多个线程共享内存空间,线程之间切换开销较小。
*创建线程的方式:
* 1.继承java.lang.Thread类,并重写run方法。
* 2.实现java.lang.Runnable接口,并重写run方法
*线程的启动:调用start()方法进行启动线程,而非调用run方法。
public class MyThread extends Thread{
public MyThread(String name){
super(name);//调用Thread的构造方法,分配新的 Thread 对象
} @Override
public void run() {
String name = getName();//获取线程的名称
for (int i = ; i < ; i++) {
System.out.println(name+"---->"+i);
}
}
}
public class MyThread2 implements Runnable{
private String name; public MyThread2(String name){
this.name=name;
} @Override
public void run() {
for (int i = ; i < ; i++) {
System.out.println(name+"======>"+i);
}
} }
public class Test {
public static void main(String[] args) {
MyThread thread1 = new MyThread("A");
MyThread2 thread2 = new MyThread2("B");
thread1.start();//启动线程A
// thread1.run(); //方法调用
Thread t = new Thread(thread2);//创建代理
t.start();//启动线程B
// t.run(); //方法调用
}
}
代理模式:
public interface KindWoman {
public void makeEyes();
}
public class PanJinLian implements KindWoman{
public void makeEyes(){
System.out.println("西门大官人,大郎出去卖了炊饼,今晚约吗?");
}
}
public class YanPoXi implements KindWoman{
public void makeEyes(){
System.out.println("西门大官人,宋押司会见梁山好汉了,今晚约吗?");
}
}
/**
* 代理
*/
public class WangPo {
// PanJinLian panJinLian;
KindWoman woman;//被代理者
public WangPo(KindWoman woman){
this.woman=woman;
} public void makeEyes(){
System.out.println("西门大官人,我是王妈妈");
woman.makeEyes();
} public static void main(String[] args) {
PanJinLian panJinLian = new PanJinLian();
WangPo wangPo = new WangPo(panJinLian);
wangPo.makeEyes();
System.out.println("--------------------");
YanPoXi yanPoXi = new YanPoXi();
WangPo wangPo2 = new WangPo(yanPoXi);
wangPo2.makeEyes();
}
}
Thread种的方法:
*java.lang.Thread类
*常用构造方法:
* Thread()
* Thread(String name)
* Thread(Runnable target)
*常用的方法:
* getName():获取线程的名称
* getId():获取线程的标识符Id
* getState()返回该线程的状态。
* getPriority() 返回线程的优先级。
* void setPriority(int newPriority):更改线程的优先级
* NORM_PRIORITY:默认优先级,值为5
* MAX_PRIORITY:最高优先级,值为10
* MIN_PRIORITY:最低优先级,值为1
* setName(String name)改变线程名称,使之与参数 name 相同。
* sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
* start():启动线程***
* run():存放线程体中代码,不能显示调用。
* isAlive():判断线程是否还“活”着,即线程是未终止
public class MyThread2 extends Thread{
private String name;//线程名称
public MyThread2(String name){
this.name=name;
} @Override
public void run() {
System.out.println("线程"+name+"开始执行....");
for (int i = ; i < ; i++) {
// try {
// Thread.sleep(1);
// } catch (InterruptedException e) {
// e.printStackTrace();
// } System.out.println(name+"----->"+i);
}
System.out.println("线程"+name+"执行结束....");
} }
public class MyThread extends Thread{
private String name;//线程名称
public MyThread(String name){
this.name=name;
} @Override
public void run() {
System.out.println("线程"+name+"开始执行...."); for (int i = ; i < ; i++) {
// try {
// Thread.sleep(1);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println(name+"----->"+i);
try {
join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程"+name+"执行结束....");
} }
public class TestThread {
public static void main(String[] args) {
Thread t = Thread.currentThread();//获取当前线程
t.setPriority(Thread.MAX_PRIORITY);//设置优先级
t.setName("主线程");
System.out.println("线程名称:"+t.getName());
System.out.println("线程Id:"+t.getId());
System.out.println("线程的优先级:"+t.getPriority());
System.out.println("程序即将休眠1秒:");
try {
t.sleep();//单位是毫秒.
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("当前线程是否活着:"+t.isAlive());
System.out.println("休眠完毕!"); }
}
public class TestMyThread {
/*
Join () 阻塞指定线程等到另一个线程完成以后再继续执行
Sleep () 使线程停止运行一段时间,将处于阻塞状态
如果调用了sleep方法之后,没有其他等待执行的线程,这个时候当前线程不会马上恢复执行!
yield () 让当前正在执行线程暂停,不是阻塞线程,而是将线程转入就绪状态
如果调用了yield方法之后,没有其他等待执行的线程,这个时候当前线程就会马上恢复执行!
*/
public static void main(String[] args) {
MyThread t1 = new MyThread("线程A");
MyThread2 t2 = new MyThread2("线程B");
// t1.setPriority(1);
t1.start();
// t2.setPriority(10);
t2.start(); }
}
通过继承Thread类是不能用一个实例建立多个线程,故而实现Runnable接口适合于资源共享;
当然,继承Thread类也能够共享变量,能共享Thread类的static变量;
*模拟实现火车站售票窗口同时售票
* 50张车票,1000人在抢票
*Thread(Runnable target, String name) 分配新的 Thread 对象。
public class TicketSell implements Runnable{
private int ticket=;//50张火车票 @Override
public void run() {
for(int i=;i<=;i++){
Thread t = Thread.currentThread();
String name = t.getName();
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(ticket>){
System.out.println(name+"卖出了"+(ticket--)+"号票");
}
}
} public static void main(String[] args) {
TicketSell ticketSell = new TicketSell();
Thread t1 = new Thread(ticketSell,"A窗口");
Thread t2 = new Thread(ticketSell,"B窗口");
Thread t3 = new Thread(ticketSell,"C窗口");
Thread t4 = new Thread(ticketSell,"D窗口");
Thread t5 = new Thread(ticketSell,"E窗口");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
} }
* 模拟实现火车站售票窗口同时售票 50张车票,1000人在抢票
* Thread(Runnable target, String name) 分配新的Thread 对象。
* 问题:多个窗口同时售票的过程中有可能出现同一张票出售给不同人。 解决方案:利用线程同步进行解决
* 同步:类似生活中排队,同一时刻只能有一个线程操作资源,在程序中可以通过加锁完成线程同步。
* 同步的优点:保证数据的有效性 同步的缺点:效率较低。
* 利用以下两种方式实现同步
* 1.在java中可以通过synchronized关键字(同步监视器)来实现同步. 同步监视器:synchronized(obj){ obj:同步监视器
* //代码; }
* 2.使用同步方法(使用synchronized关键字修饰的方法)进行加锁
public class TicketSell3 implements Runnable {
private Integer ticket = new Integer();// 50张火车票 @Override
public void run() {
for (int i = ; i <= ; i++) {
Thread t = Thread.currentThread();
String name = t.getName();
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
sale(name);
}
}
/**
* 同步的方法:
* @param name
*/
public synchronized void sale(String name) {
if (ticket > ) {
System.out.println(name + "卖出了" + (ticket--) + "号票");
}
} public static void main(String[] args) {
TicketSell3 ticketSell = new TicketSell3();
Thread t1 = new Thread(ticketSell, "A窗口");
Thread t2 = new Thread(ticketSell, "B窗口");
Thread t3 = new Thread(ticketSell, "C窗口");
Thread t4 = new Thread(ticketSell, "D窗口");
Thread t5 = new Thread(ticketSell, "E窗口");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
} }
eg2:
public class BankAccount implements Runnable{
int blance=;
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name+"开始取款....."+blance);
for(int i=;i<;i++){
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
// synchronized (this) { //利用同步监视器实现线程同步
// if(blance>100){
// blance=blance-100;
// System.out.println(name+"取款100,余额为:"+blance);
// }
// }
draw();
}
}
/**
* 利用同步方法实现线程同步
*/
public synchronized void draw(){
String name = Thread.currentThread().getName();
if(blance>){
blance=blance-;
System.out.println(name+"取款100,余额为:"+blance);
}
} public static void main(String[] args) {
BankAccount bc = new BankAccount();
Thread t1 = new Thread(bc, "张三");
t1.start();
Thread t2 = new Thread(bc,"张三老婆");
t2.start();
} }
*死锁:当两个线程相互等待对方释放“锁”时就会发生死锁
*出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续
*线程同步的优点:保证线程安全(数据安全有效)
*线程同步的缺点:效率低,有可能造成死锁问题。
public class TestDeadLock {
public static void main(String[] args) {
final DeadLock d1 = new DeadLock();
final DeadLock d2 = new DeadLock();
//使用匿名类创建线程
new Thread("线程A"){
public void run() {
//调用d1的m1方法是需要对d2对象进行加锁
d1.m1(d2);//匿名类访问外部的成员变量时,该成员必须使用final修饰
};
}.start();
//使用匿名类创建线程
new Thread("线程B"){
public void run() {
//调用d2的m1方法是需要对d1对象进行加锁
d2.m1(d1);//匿名类访问外部的成员变量时,该成员必须使用final修饰
};
}.start();
}
}
public class DeadLock {
public synchronized void m1(DeadLock deadLock){
String name = Thread.currentThread().getName();
System.out.println(name+"进入m1方法....");
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+"即将调用m2方法....");
deadLock.m2();
} public synchronized void m2(){
String name = Thread.currentThread().getName();
System.out.println(name+"进入m2方法....");
}
}
*java.util.Timer类:定时器,一种工具,线程用其安排以后在后台线程中执行的任务
*java.util.TimerTask类实现Runnable接口,由 Timer 安排为一次执行或重复执行的任务。
*常用的构造方法:
* Timer()创建一个新计时器。
*常用的方法:
* schedule(TimerTask task, Date time)安排在指定的时间执行指定的任务。
* schedule(TimerTask task, long delay)安排在指定延迟后执行指定的任务。
* schedule(TimerTask task, Date firstTime, long period)
* 安排指定的任务在指定的时间开始进行重复的固定延迟执行。
* schedule(TimerTask task, long delay, long period)安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。
public class MyTimerTask extends TimerTask{ @Override
public void run() {
System.out.println("执行了MyTimerTask中的run方法。");
} public static void main(String[] args) {
Timer timer = new Timer();
// timer.schedule(new MyTimerTask(), new Date());//在当前时间执行MyTimerTask中的任务(调用其中run方法)
// timer.schedule(new MyTimerTask(), 5000);//延迟5000毫秒执行任务调度(调用MyTimerTask中run方法)
// timer.schedule(new MyTimerTask(),new Date(),2000);//从当前时间开始,每个2000毫秒做一次任务调度
timer.scheduleAtFixedRate(new MyTimerTask(), , );//延迟5000毫秒,每个2000毫秒执行一次任务调度
} }
生产者和消费者:
/**
* 馒头类
* @author Administrator
*
*/
public class SteamBread {
private int id;//馒头的编号 public SteamBread(int id){
this.id=id;
} @Override
public String toString() {
return "SteamBread [id=" + id + "]";
} }
/**
* 盛放产品的容器(匡)
* 1.生产者生成完产品之后将产品放入容器中,如果容器满了,停止生产并通知消费者进行消费
* 2.消费者从容器中取出产品进行消费,如果容器空了,停止消费并通知生产者者进行生成
*
* @author Administrator
*
*/
public class SyncStack {
int index=;//执行馒头的存储位置
SteamBread[] sb = new SteamBread[];//容器
/**
* 入栈:将生成者生成的馒头保存到匡中
*/
public synchronized void push(SteamBread s){
//判断匡是否已满
if(index==sb.length-){
try {
this.wait();//停止生产
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();//唤醒消费者线程进行消费
//将馒头添加到匡中
sb[index++]=s;
} /**
* 出栈:消费者从匡中获取馒头
* @return
*/
public synchronized SteamBread pop(){
if(index==){
try {
this.wait();//停止消费
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();//唤醒生成者进行生产
this.index--;//push第n个之后,this.index++,使栈顶为n+1,故return之前要减一
return sb[index];
}
}
/*
*
生产者
* @author Administrator
*
*/
public class Producer implements Runnable{
SyncStack ss;//匡
public Producer(SyncStack ss) {
this.ss=ss;
} @Override
public void run() {
for(int i=;i<;i++){
System.out.println("生产者开始生产---->");
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
SteamBread s = new SteamBread(i);
System.out.println("生产了:"+s);
ss.push(s); }
} }
/**
* 消费者
* @author Administrator
*
*/
public class Consume implements Runnable{
SyncStack ss;//匡
public Consume(SyncStack ss) {
this.ss=ss;
} @Override
public void run() {
for(int i=;i<;i++){
System.out.println("消费者开始消费---->");
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
SteamBread s = ss.pop();
System.out.println("消费者拿走了---->"+s+"号馒头");
}
} }
public class Test {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
Producer producer = new Producer(ss);
Consume consume = new Consume(ss);
Thread t = new Thread(producer);
Thread t2 = new Thread(consume);
t.start();
t2.start();
}
}
java:多线程(代理模式,Thread中的方法,Timer,生产者和消费者)的更多相关文章
- java多线程2:Thread中的方法
静态方法: Thread类中的静态方法表示操作的线程是"正在执行静态方法所在的代码块的线程". 为什么Thread类中要有静态方法,这样就能对CPU当前正在运行的线程进行操作.下面 ...
- Java多线程4:Thread中的静态方法
一.Thread类中的静态方法 Thread类中的静态方法是通过Thread.方法名来调用的,那么问题来了,这个Thread指的是哪个Thread,是所在位置对应的那个Thread嘛?通过下面的例子可 ...
- Java多线程2:Thread中的实例方法
Thread类中的方法调用方式: 学习Thread类中的方法是学习多线程的第一步.在学习多线程之前特别提出一点,调用Thread中的方法的时候,在线程类中,有两种方式,一定要理解这两种方式的区别: 1 ...
- Java多线程3:Thread中的实例方法
一.Thread类中的方法调用方式 学习Thread类中的方法是学习多线程的第一步.在学习多线程之前特别提出一点,调用Thread中的方法的时候,在线程类中,有两种方式,一定要理解这两种方式的区别: ...
- Java多线程3:Thread中start()和run()的区别
原文:http://www.cnblogs.com/skywang12345/p/3479083.html start() 和 run()的区别说明start():它的作用是启动一个新线程,新线程会执 ...
- Java多线程3:Thread中的静态方法
Thread类中的静态方法 Thread类中的静态方法表示操作的线程是"正在执行静态方法所在的代码块的线程".为什么Thread类中要有静态方法,这样就能对CPU当前正在运行的线程 ...
- Java多线程12:ReentrantLock中的方法
公平锁与非公平锁 ReentrantLock有一个很大的特点,就是可以指定锁是公平锁还是非公平锁,公平锁表示线程获取锁的顺序是按照线程排队的顺序来分配的,而非公平锁就是一种获取锁的抢占机制,是随机获得 ...
- java多线程20 : ReentrantLock中的方法 ,公平锁和非公平锁
公平锁与非公平锁 ReentrantLock有一个很大的特点,就是可以指定锁是公平锁还是非公平锁,公平锁表示线程获取锁的顺序是按照线程排队的顺序来分配的,而非公平锁就是一种获取锁的抢占机制,是随机获得 ...
- Java多线程系列二——Thread类的方法
Thread实现Runnable接口并实现了大量实用的方法 public static native void yield(); 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将可能得到执行机 ...
- java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)
*java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时 ...
随机推荐
- Gym - 101173H Hangar Hurdles (kruskal重构树/最小生成树+LCA)
题目大意:给出一个n*n的矩阵,有一些点是障碍,给出Q组询问,每组询问求两点间能通过的最大正方形宽度. 首先需要求出以每个点(i,j)为中心的最大正方形宽度mxl[i][j],可以用二维前缀和+二分或 ...
- HDU - 6393 Traffic Network in Numazu (基环树+树链剖分/LCA)
题意:给定一个带权边无向基环树,有两种操作,一种是改变某个边的权值,另一种是询问两点间的最短路径. 可以对环进行缩点,以环为根建立一棵新树,并记录与环相连的所有点和环上的哪个点相连,将路径分为环外和环 ...
- 【BZOJ3534】【Luogu P3317】 [SDOI2014]重建 变元矩阵树,高斯消元
题解看这里,主要想说一下以前没见过的变元矩阵树还有前几个题见到的几个小细节. 邻接矩阵是可以带权值的.求所有生成树边权和的时候我们有一个基尔霍夫矩阵,是度数矩阵减去邻接矩阵.而所谓变元矩阵树实际上就是 ...
- UML(Rational Rose)安装教程【载百度经验】
---恢复内容开始--- Win7安装rational rose2007教程 在UML建模的众多工具中,IBM公司的rational rose建模工具可以说是最好用的建模工具了.哪我们又该如何在win ...
- 判断当前环境是ios还是安卓
/** * @name 判断iOS */ export const isiOS = ()=>{ let u = navigator.userAgent; let iOs = !!u.match( ...
- k8s配置文件模板
一,deployment Deployment为Pod和Replica Set下一代Replication Controller)提供声明式更新 1,配置示例 apiVersion: apps/v1 ...
- 数组翻转的方法(java实现)
数组翻转的方法(java实现),所谓数组翻转,就是将数组倒置,例如原数组为:{"a","b","c","d"},那么翻转 ...
- Java多线程和并发(五),线程的状态
目录 1.线程的六个状态 2.sleep和wait的区别 3.锁池(EntryList)和等待池(WaitSet) 4.notify和notifyall的区别 五.线程的状态 1.线程的六个状态 2. ...
- SpringBoot整合Elastic-job(详细)
一 作业分片1.分片概念作业分片是指任务的分布式执行,需要将一个任务拆分为多个独立的任务项,然后由分布式的应用实例分别执行某一个或几个分片项.例如:Elastic-Job快速入门中文件备份的例子,现有 ...
- vim文件编辑器
Vim 是 Vi 的增强版(在 Vi 的基础上增加了正则表达式的查找.多窗口的编辑等功能),使用 Vim 进行程序开发会更加方便. 想深入了解 Vi 和 Vim 的区别,可以在 Vim 命令模式下输入 ...