*进程:一个正在运行的程序,进程是操作系统分配资源的基本单位,每个进行有独立的内存空间,进程之间切换开销较大。
*线程:一个轻量级的进程,线程是任务调度的基本单位,一个进程可以有多个线程,
* 系统没有为线程分配额外的内存空间,一个进程中的多个线程共享内存空间,线程之间切换开销较小。
*创建线程的方式:
* 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,生产者和消费者)的更多相关文章

  1. java多线程2:Thread中的方法

    静态方法: Thread类中的静态方法表示操作的线程是"正在执行静态方法所在的代码块的线程". 为什么Thread类中要有静态方法,这样就能对CPU当前正在运行的线程进行操作.下面 ...

  2. Java多线程4:Thread中的静态方法

    一.Thread类中的静态方法 Thread类中的静态方法是通过Thread.方法名来调用的,那么问题来了,这个Thread指的是哪个Thread,是所在位置对应的那个Thread嘛?通过下面的例子可 ...

  3. Java多线程2:Thread中的实例方法

    Thread类中的方法调用方式: 学习Thread类中的方法是学习多线程的第一步.在学习多线程之前特别提出一点,调用Thread中的方法的时候,在线程类中,有两种方式,一定要理解这两种方式的区别: 1 ...

  4. Java多线程3:Thread中的实例方法

    一.Thread类中的方法调用方式 学习Thread类中的方法是学习多线程的第一步.在学习多线程之前特别提出一点,调用Thread中的方法的时候,在线程类中,有两种方式,一定要理解这两种方式的区别: ...

  5. Java多线程3:Thread中start()和run()的区别

    原文:http://www.cnblogs.com/skywang12345/p/3479083.html start() 和 run()的区别说明start():它的作用是启动一个新线程,新线程会执 ...

  6. Java多线程3:Thread中的静态方法

    Thread类中的静态方法 Thread类中的静态方法表示操作的线程是"正在执行静态方法所在的代码块的线程".为什么Thread类中要有静态方法,这样就能对CPU当前正在运行的线程 ...

  7. Java多线程12:ReentrantLock中的方法

    公平锁与非公平锁 ReentrantLock有一个很大的特点,就是可以指定锁是公平锁还是非公平锁,公平锁表示线程获取锁的顺序是按照线程排队的顺序来分配的,而非公平锁就是一种获取锁的抢占机制,是随机获得 ...

  8. java多线程20 : ReentrantLock中的方法 ,公平锁和非公平锁

    公平锁与非公平锁 ReentrantLock有一个很大的特点,就是可以指定锁是公平锁还是非公平锁,公平锁表示线程获取锁的顺序是按照线程排队的顺序来分配的,而非公平锁就是一种获取锁的抢占机制,是随机获得 ...

  9. Java多线程系列二——Thread类的方法

    Thread实现Runnable接口并实现了大量实用的方法 public static native void yield(); 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将可能得到执行机 ...

  10. java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)

     *java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时 ...

随机推荐

  1. Hdu第八场 树形dp+基环树

    Card Game 每个牌背面的数字朝正面的数字连一条有向边 则题目变为问你最少翻转多少次 能使得每个数字的入度不超过1 首先判断图中每个连通块是不是树或者基环树 因为只有树或者基环树能使得每个点的入 ...

  2. Kattis - bitwise Bitwise (RMQ+尺取+树上dfs)

    题意:有一个长度为n的序列,让你把它分成k段,段内元素取or,段间取and,求能够得到的最大值. 这个算法是我和xz场上yy出来的,然而时间不够了没写出来,而且时间复杂度是$O(nlogn+nlogA ...

  3. 在github新建一个项目里需要哪些文件及作用

    1.README.md文件 关于项目的介绍和使用方法. 2.  .gitignore文件 上传项目时不需要传的文件,最常用的就是“node_modules/",如下: 详细的介绍可以去git ...

  4. HGOI 20190519 题解

    脑补了一下今天的比赛难度和之前zju-lzw出的题目画风迥异. 难度完全不是一个水平的好伐. Probem A palindrome 给出一个$n$个元素的数组,可以任意指定一个数字$m$让所有$a_ ...

  5. VS Code 最好用的 Markdown 插件

    对经常使用 Markdown 写东西的工程师来说找到称手好用的 Markdown 编辑器非常重要. 目前为止 VS Code 最好用的插件是 Markdown Preview Enhanced . 各 ...

  6. BZOJ 3456 城市规划 (组合计数、DP、FFT)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3456 著名的多项式练习题,做法也很多,终于切掉了纪念 首先求一波递推式: 令\(F(n ...

  7. 博主的OI流水账

    2017.8.4 入坑OI 2017.11.11 参加了NOIP2017提高组,0+85+0+30+50+0=165,荣获省二(具体分数其实记不清了反正差不多吧) 2018.2 学会树状数组,线段树 ...

  8. [LOJ3106][TJOI2019]唱、跳、rap和篮球:DP+生成函数+NTT+容斥原理

    分析 令\(f(i)\)表示共\(i\)组同学讨论cxk的位置的方案数(不考虑其他位置上的人的爱好),这个数组可以很容易地通过依次考虑每个位置是否是四个人中最后一个人的位置来递推求解,时间复杂度\(O ...

  9. STS(Spring tool suite)集成配置jdk,maven和Tomcat

    STS是spring官网的一个集成开发工具,最近在学springboot,所以用了. 在本文中将介绍如下内容: 搭建开发的 JDK(1.8) 环境. 配置 Maven 环境. 配置 Tomcat 环境 ...

  10. VS2015 ASP.NET MVC5 EntityFramework6 Oracle 环境篇

    //来源:https://www.cnblogs.com/lauer0246/articles/9576940.html Asp.Net MVC EF各版本区别 2009年發行ASP.NET MVC ...