多线程编程
线程
线程的由来
单任务操作系统
一次执行一个应用
多任务OS
进程:每一个进程对应一个应用程序
每个应用分配独立内存,相互之间不干扰 CPU在他们之间来回切换
线程
一个进程内部的一个独立的执行分支
特点:共享内存地址空间
实现方式一
extends Thread 重写run方法,run方法只负责确定这个线程要做的事情。
开启线程:调用start方法–该方法会为线程分配资源,然后自动调用this.run()方法。
如果调用run方法,不会报错,但只是普通方法的调用,没有开启新线程。
实现方式二
实现runnable 接口 ,重写run方法。创建一个thread对象 ,把runnable 接口实现类对象传入 ,调用thrad 对象的start方法 。
同一个进程可以有很多线程
主线程(main线程)
子线程 地位和主线程一样
开始一定是主线程,结束不一定是主线程
GC垃圾回收线程
打印异常线程
死亡状态:线程run方法执行完毕,回收清理
运行状态:start 调用 run方法。
中断状态:在运行中由于种种原因,没有得到CPU 的执行,
原因:五种
由于CPU在执行其他线程,本线程没有得到执行
线程的优先级(共十级)。最高为10 ,最低为1。
优先级高的只是被执行的几率更大,不代表一定先执行完高的才会执行低的线程
由于I/O输入或输出的等待,造成该线程进入中断状态。我们叫阻塞 。scanner 阻塞完毕,继续抢CPU
休眠状态:主动调用Thread 的sleep方法 给一个毫秒数,休眠完毕,继续抢CPU
等待与唤醒机制:Object 的wait方法 等待方法 notify方法 唤醒方法 唤醒等待的第一个方法 。 notifyall 唤醒所有。
挂起:yield方法,强制让某个程序退出去。
就绪状态:调用start方法。但在start调用run之前
线程状态:新建状态: new Thread()对象
线程安全(同步)synchronized
凡是线程安全的,效率都低
才会考虑线程安全性问题
锁机制,同步锁
一次只能执行一个线程,只有此线程执行完毕,下一个线程才能进入资源操作资源
当多个线程访问
同一个资源
的时候,有可能造成该资源数据混乱,为保证该资源每次只能被一个线程使用,使用完以后再交给下一个线程,我们要使用同步技术。
同步的第一种实现:同步方法
在资源身上加同步关键字synchronized
同步的第二种实现:同步块
在调用资源的线程身上使用关键字 synchronized
synchronized(this.rs){
this.rs.show();
}
包装类 所有包装类对象看起来传递的是引用,其实不是,传的是值 ,不像引用类型传的是引用。
死锁 两个线程依赖一对同步资源发生。
线程间通信 wait notify notifyall 让某个线程等待,一个线程执行完毕后 ,在唤醒
wait notify notifyall 必须在synchronized 里面调用
生产者与消费者
生产者线程
消费者线程
package com.lovo.syn;
/*
* 当多个线程访问同一资源的时候,有可能造成该资源数据混乱.
* 为保证该资源每次只能被一个线程使用,使用完以后再交给下一个
* 线程,我们要使用同步技术
*/
//资源类
public class Resource {
//资源方法
/*
* 同步的第一种实现:同步方法
* 在资源身上加同步关键字synchronized
*/
// public synchronized void show(String name){
public void show(String name){
for(int i = 0; i < 5; i++){
System.out.println("线程" + name + "执行资源" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package com.lovo.syn;
public class SynThread extends Thread{
private Resource rs;
public SynThread(String name,Resource rs) {
// TODO Auto-generated constructor stub
this.rs = rs;
this.setName(name);
this.start();
}
@Override
public void run() {
// TODO Auto-generated method stub
/*
* 同步的第二种实现:同步块
* 在调用资源的线程身上使用synchronized
*/
synchronized(this.rs){
this.rs.show(this.getName());
}
}
}
package com.lovo.thread;
//线程的实现方式一:
//继承Thread类,重写run方法----run方法只负责确定这个线程要做的事情
//开启线程,要调用start方法----该方法会为线程分配资源,然后自动调用this.run()
// 如果调用run方法----不会报错,但只是普通的方法调用,没有开启新线程
public class MyThread extends Thread{
private int num;
public MyThread() {
super();
this.setPriority(Thread.MIN_PRIORITY);
this.start();
}
public MyThread(int num) {
super();
this.num = num;
this.start();//开启线程
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0; i < 100; i++){
System.out.println("MyThread " + num + "=============" + i);
}
}
}
package com.lovo.thread;
//线程实现方式二
//实现Runnable接口,重写run方法
//创建一个Thread对象,把Runnable接口的实现类对象传入
//调用Thread对象的start()
public class YourThread implements Runnable{
private int num;
public YourThread() {
Thread th = new Thread(this);
//线程优先级共十级,最高为10,最低为1
//优先级高的只是被执行的几率更大,不代表完胜优先级底的
th.setPriority(Thread.MAX_PRIORITY);
th.start();
}
public YourThread(int num){
this.num = num;
Thread th = new Thread(this);
th.start();
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0; i < 100; i++){
System.out.println("YourThread " + this.num + "=============" + i);
}
}
}
//生产者
public class Producer extends Thread{
private Queue q;
public Producer(Queue q){
this.q = q;
}
public void run(){
for(int i = 0; i < 10; i++){
q.put(i);
}
}
}
//消费者
public class Customer extends Thread{
private Queue q;
public Customer(Queue q){
this.q = q;
}
public void run(){
for(int i = 0; i < 10; i++){
int value = q.get();
}
}
}
package com.lovo.waitnotify;
//柜台
public class Queue {
int value;
boolean bFull = false;
synchronized public void put(int i){
if(bFull == false){
value = i;
bFull = true;
System.out.println("producer put " + i);
notify();
}
try{
wait();
}catch(Exception e){
e.printStackTrace();
}
}
synchronized public int get(){
if(bFull == false){
try{
wait();
}catch(Exception e){
e.printStackTrace();
}
}
bFull = false;
System.out.println("customer get " + value);
notify();
return value;
}
}