多线程
- 概念
- 进程
- 实现线程方法
- start启动一个线程
- run方法启动一个线程要执行的操作
- isAlive方法
- join合并线程
- yield让出cup
- 线程优先级
- 线程同步
- 生产者与消费者经典问题
概念:程序里面的不同执行路径就是线程(例如主线程main方法里面可以除了main主线程,还可以继承thread方法,调用线程的start()启动一个线程,这样一个程序里面就有两个线程在交替执行
进程:正在运行的程序的实例(进程既是一个实体,也是一个运行中的程序)
实现线程的方法:一种是继承Thread类,另一种是实现runnable接口。
start方法:start方法是启动线程的方法(调用start方法会告诉cpu,现在启动了一个新线程)
run方法:启动一个新线程有什么操作要执行就写在run方法中
isAlive方法:线程是否还活着
join方法:与当前线程合并(原本并行执行的两个线程,现在合并成一个线程,等着前面的线程执行完了,在执行主线程)
yield方法:让出CPU,给其他线程执行(几个线程原本是并行执行的,其中有个线程调用了yield方法,其他几个线程就先执行)
线程优先级:setPriority(default)设置线程的优先级,默认的优先级为5。优先级高的线程先执行
线程同步:在某个时刻,某个方法或某个类只能有一个线程访问
(夫妻取钱问题,丈夫拿存在取钱,妻子拿卡取钱,在同一个时刻,都在进行取钱操作,如果取钱操作没被锁定的话,银行就会亏钱了。)
Timer问题
package com.huahua.it.thread;
public class TestSyn implements Runnable {
public Timer timer=new Timer();
public static void main(String[] args) {
TestSyn ts=new TestSyn();
Thread t=new Thread(ts);
Thread t1=new Thread(ts);
t.start();
t1.start();
}
public void run(){
timer.add(Thread.currentThread().getName());
}
}
class Timer{
public static int num=0;
public synchronized void add(String name){
num++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+”:你是第Timer添加的第”+num+”个线程”);
}
}
如果add方法不设置成同步,数据变出现错误了
线程死锁:多个线程同时访问类的两个Object对象,t1线程获得Object1对象的锁,t2线程获得Object2对象的锁,t1线程要结束必须要获得Object2对象的锁,t2要结束必须获取的Object1对象的锁,这样就形成了死锁
package com.huahua.it.thread;
public class TestDeadLock implements Runnable{
public int flag=1;
public static Object o1= new Object(),o2=new Object();
public static String str1=”obj1”;
public static String str2=”obj2”;
public void run(){
System.out.println(“flag=”+flag);
if(flag==1){
synchronized (str1) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (str2) {
System.out.println("o2");
}
}
}
if(flag==0){
synchronized (str2) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (str1) {
System.out.println("o1");
}
}
}
}
public static void main(String[] args) {
TestDeadLock lock=new TestDeadLock();
TestDeadLock lock1=new TestDeadLock();
Thread t1=new Thread(lock);
Thread t2=new Thread(lock1);
lock.flag=1;
lock1.flag=0;
t1.start();
t2.start();
}
}
经典生产者与消费者问题
生产者生产馒头,把馒头扔进一个筐中,消费者从筐中取出一个馒头。有四个对象,筐中有馒头,馒头,生产者有筐的引用,消费者有筐的引用。筐中的馒头是先扔进去的后取出来,这个筐可以设计为stack对象,pop取顶部的馒头,push把馒头扔到顶部。当馒头生产6个后,释放当前对象的锁,给消费者取馒头的机会。当馒头被清空了,释放当前对象的锁,给机会生产者继续生产馒头
package com.huahua.it.thread;
public class ProductConsumer {
public static void main(String[] args) {
SynStack ss=new SynStack();
Produce p=new Produce(ss);
Consumer c=new Consumer(ss);
Thread t1=new Thread(p);
Thread t2=new Thread(c);
t1.start();
t2.start();
}
}
class WoTou{
int id;
public WoTou(int id){
this.id=id;
}
public String toString(){
return “wotou:”+id;
}
}
class SynStack{
WoTou wo[]=new WoTou[6];
int index=0;
public synchronized void push(WoTou w){
while(index==wo.length){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
wo[index]=w;
index++;
}
public synchronized WoTou pop(){
while(index==0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(index);
this.notify();
index–;
return wo[index];
}
}
class Produce implements Runnable{
SynStack ss=null;
public Produce(SynStack ss){
this.ss=ss;
}
public void run(){
for (int i = 0; i < 20; i++) {
WoTou t=new WoTou(i);
ss.push(t);
System.out.println(“我们生产了”+t);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable{
SynStack ss=null;
public Consumer(SynStack ss){
this.ss=ss;
}
public void run(){
for (int i = 0; i<20; i++) {
WoTou w=ss.pop();
System.out.println(“我们消费了”+w);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}