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.消费者仅仅在有产品的时 ...
随机推荐
- 关于log4j的配置文件
因为要在spring中添加Mongodb,在网上查阅资料的时候我发现有人在web.xml中添加如下代码: <context-param> <param-name>l ...
- 【BZOJ1176】Mokia
题目大意:给定一个 N*N 的矩形,有 Q 次操作,每个操作可以是矩形单点修改或查询子矩形的权值和. 题解:CDQ分治适合处理修改操作之间互不影响且支持离线的题目. 满足以上操作条件的显然可以树套树来 ...
- Phantomjs 请求与响应
var page = require('webpage').create(); page.onResourceRequested = function(request) { console.log(' ...
- 【leetcode】815. Bus Routes
题目如下: We have a list of bus routes. Each routes[i] is a bus route that the i-th bus repeats forever. ...
- ASP.NET大文件上传断点续传解决方案
HTML部分 <%@PageLanguage="C#"AutoEventWireup="true"CodeBehind="index.aspx. ...
- cogs1619. [HEOI2012]采花 x
1619. [HEOI2012]采花 ★★☆ 输入文件:1flower.in 输出文件:1flower.out 简单对比时间限制:5 s 内存限制:128 MB [题目描述] 萧薰儿是 ...
- python类装饰器即__call__方法
上一篇中我对学习过程中的装饰器进行了总结和整理,这一节简单整理下类装饰器 1.类中的__call__方法: 我们在定义好一个类后,实例化出一个对象,如果对这个对象以直接在后边加括号的方式进行调用,程序 ...
- 在vue中如何安装使用Vant
---恢复内容开始--- Vant中文文档地址:https://youzan.github.io/vant-weapp 1.创建Vue项目之后,运行安装命令:13:47:04 npm i vant - ...
- CSS Selectors
CSS selectors are used to "find" (or select) HTML elements based on their element name, id ...
- TreeMap、HashMap、LindedHashMap的区别
LinkedHashMap可以保证HashMap集合有序.存入的顺序和取出的顺序一致.TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器 ...