/*
生产者消费者
生产者负责生产,有生产任务
消费之负责消费,有消费任务
生产和消费可以同时进行
既然要同时进行,就得使用多线程
需要描述生产任务
描述消费任务
生产和消费的都是产品
还需要对产品进行描述
一个生产者线程,一个消费者线程,程序运行没问题
*/
//描述产品
class Product
{
private String name;
private int count;
private boolean flag = false;
//生产产品
public synchronized void produce(String name)
{
if(flag)
try{this.wait();}catch(InterruptedException e){e.printStackTrace();}
this.name = name+"...."+count;
count++;
System.out.println(Thread.currentThread().getName()+"生产了..."+this.name);
flag = true;
this.notify();
}
//消费产品
public synchronized void consume()
{
if(!flag)
try{this.wait();}catch(InterruptedException e){e.printStackTrace();}
System.out.println(Thread.currentThread().getName()+"....消费了..."+this.name);
flag = false;
this.notify();
}
}
//描述生产任务
class Producer implements Runnable
{
private Product product = null;
public Producer(Product product)
{
this.product = product;
}
public void run()
{
while(true)
{
product.produce("笔记本");
}
}
}
//描述 消费任务
class Consumer implements Runnable
{
private Product product = null;
public Consumer(Product product)
{
this.product = product;
}
public void run()
{
while(true)
{
product.consume();
}
}
}
class Demo2
{
public static void main(String[] args)
{
//创建产品对象
Product pro = new Product();
//创建生产任务对象
Producer producer = new Producer(pro);
//创建消费任务对象
Consumer consumer = new Consumer(pro);
//创建生产者线程
Thread t0 = new Thread(producer);
//创建消费者线程
Thread t1 = new Thread(consumer);
t0.start();
t1.start();
}
}
/*
生产者消费者
生产者负责生产,有生产任务
消费之负责消费,有消费任务
生产和消费可以同时进行
既然要同时进行,就得使用多线程
需要描述生产任务
描述消费任务
生产和消费的都是产品
还需要对产品进行描述
一个生产者线程,一个消费者线程,程序运行没问题
多个生产者线程,duoge消费者线程,程序运行出现了问题
出现了生产多次,消费一次,或者生产一次,消费多次的现象
出现问题的原因:一个线程被唤醒之后,没有去判断标记,直接执行
下边的代码
解决方式: 把if判断改成while判断,让每个被 唤醒的线程先去判断标记
而不是直接去生产后消费
该成while判断之后,又出现了死锁的问题
出现死锁的原因:因为notify()唤醒的是线程池中的任意一个线程,所以可能唤醒的是本方线程,导致所有线程等待
解决方式:还有一个notifyAll() 方法,唤醒的是线程池中的所有的线程,这样就能保证唤醒对方的线程了
使用notifyAll()唤醒线程池中的所有线程,解决了问题,但是不需要被唤醒的也被唤醒了,程序性能降低
从jdk1.5解决了一次唤醒所有线程,性能低的问题
*/
//描述产品
class Product
{
private String name;
private int count;
private boolean flag = false;
//生产产品
public synchronized void produce(String name)
{
while(flag)
{
try{
this.wait();//t0,t1
}catch(InterruptedException e)
{e.printStackTrace();}
}
this.name = name+"...."+count;
count++;
System.out.println(Thread.currentThread().getName()+"生产了..."+this.name);
flag = true;
//this.notify();
notifyAll();
}
//消费产品
public synchronized void consume()
{
while(!flag)
{
try{this.wait();}
catch(InterruptedException e)
{e.printStackTrace();}
}
System.out.println(Thread.currentThread().getName()+"....消费了..."+this.name);
flag = false;
//this.notify();
notifyAll();//唤醒所有等待线程
}
}
//描述生产任务
class Producer implements Runnable
{
private Product product = null;
public Producer(Product product)
{
this.product = product;
}
public void run()
{
while(true)
{
product.produce("笔记本");
}
}
}
//描述 消费任务
class Consumer implements Runnable
{
private Product product = null;
public Consumer(Product product)
{
this.product = product;
}
public void run()
{
while(true)
{
product.consume();
}
}
}
class Demo3
{
public static void main(String[] args)
{
//创建产品对象
Product pro = new Product();
//创建生产任务对象
Producer producer = new Producer(pro);
//创建消费任务对象
Consumer consumer = new Consumer(pro);
//创建生产者线程
Thread t0 = new Thread(producer);
Thread t1 = new Thread(producer);
//创建消费者线程
Thread t2 = new Thread(consumer);
Thread t3 = new Thread(consumer);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
/*
jdk1.5实现多线程的方式:
jdk1.5之前使用的是同步代码块,对锁的操作是隐式的
synchronized(对象)//获取锁
{
}//释放锁
jdk1.5开始对锁的操作就是显示的了:专门为锁定义了描述的接口,Lock
1:获取锁 lock()
2:释放锁 unlock()
Lock可以替代同步代码块
1:创建一把锁,使用Lock的子类ReentranLock
2:把需要同步的代码放在lock()和unlock()之间
使用Lock,把锁替换后,出现了IllegalMonitorStateException,无效的监视器状态异常
同步代码块没有了,而wait(),notify(),notifyAll()还必须用在同步代码块中,
所以出现异常
解决方式就得看新的jdk1.5的api,发现有一个 和Lock相关的Condition接口,该接口中定义了
await(),signal(),signalAll()方法,替代了之前的wait(),notify(),notifyAll()三个方法,
因为单独对这三个方法进行了描述,所以更加的面向对象
使用Lock的newCondition方法,得到一个和锁绑定的Condition对象,从而实现唤醒等待的互斥
*/
//描述产品
import java.util.concurrent.locks.*;
class Product
{
private String name;
private int count;
private boolean flag = false;
// 创建一把锁
Lock lock = new ReentrantLock();
//创建和锁绑定的Condition对象
Condition con = lock.newCondition();
//生产产品
public void produce(String name)
{
lock.lock();//获取锁
try{
while(flag)
{
try{
con.await();
}catch(InterruptedException e)
{e.printStackTrace();}
}
this.name = name+"...."+count;
count++;
System.out.println(Thread.currentThread().getName()+"生产了..."+this.name);
flag = true;
//this.notify();
con.signalAll();
}
finally{
lock.unlock();//释放锁
}
}
//消费产品
public void consume()
{ lock.lock();
try{
while(!flag)
{
try{con.await();}
catch(InterruptedException e)
{e.printStackTrace();}
}
System.out.println(Thread.currentThread().getName()+"....消费了..."+this.name);
flag = false;
//this.notify();
con.signalAll();//唤醒所有等待线程
}finally{
lock.unlock();
}
}
}
//描述生产任务
class Producer implements Runnable
{
private Product product = null;
public Producer(Product product)
{
this.product = product;
}
public void run()
{
while(true)
{
product.produce("笔记本");
}
}
}
//描述 消费任务
class Consumer implements Runnable
{
private Product product = null;
public Consumer(Product product)
{
this.product = product;
}
public void run()
{
while(true)
{
product.consume();
}
}
}
class Demo4
{
public static void main(String[] args)
{
//创建产品对象
Product pro = new Product();
//创建生产任务对象
Producer producer = new Producer(pro);
//创建消费任务对象
Consumer consumer = new Consumer(pro);
//创建生产者线程
Thread t0 = new Thread(producer);
Thread t1 = new Thread(producer);
//创建消费者线程
Thread t2 = new Thread(consumer);
Thread t3 = new Thread(consumer);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
/*
使用jdk1.5的Lock和Conditiong,解决多生产多消费,一次唤醒所有线程性能低的问题
一次只唤醒一个对方线程
*/
//描述产品
import java.util.concurrent.locks.*;
class Product
{
private String name;
private int count;
private boolean flag = false;
// 创建一把锁
Lock lock = new ReentrantLock();
//创建和锁绑定的Condition对象,负责生产线程的等待和唤醒
Condition pro = lock.newCondition();
//创建和锁绑定的Condition对象,负责消费线程的等待和唤醒
Condition con = lock.newCondition();
//生产产品
public void produce(String name)
{
lock.lock();//获取锁
try{
while(flag)
{
try{ pro.await();}catch(InterruptedException e){e.printStackTrace();}
}
this.name = name+"...."+count;
count++;
System.out.println(Thread.currentThread().getName()+"生产了..."+this.name);
flag = true;
//this.notify();
con.signal();
}
finally{
lock.unlock();//释放锁
}
}
//消费产品
public void consume()
{ lock.lock();
try{
while(!flag)
{
try{con.await();}
catch(InterruptedException e)
{e.printStackTrace();}
}
System.out.println(Thread.currentThread().getName()+"....消费了..."+this.name);
flag = false;
//this.notify();
pro.signal();//唤醒所有等待线程
}finally{
lock.unlock();
}
}
}
//描述生产任务
class Producer implements Runnable
{
private Product product = null;
public Producer(Product product)
{
this.product = product;
}
public void run()
{
while(true)
{
product.produce("笔记本");
}
}
}
//描述 消费任务
class Consumer implements Runnable
{
private Product product = null;
public Consumer(Product product)
{
this.product = product;
}
public void run()
{
while(true)
{
product.consume();
}
}
}
class Demo5
{
public static void main(String[] args)
{
//创建产品对象
Product pro = new Product();
//创建生产任务对象
Producer producer = new Producer(pro);
//创建消费任务对象
Consumer consumer = new Consumer(pro);
//创建生产者线程
Thread t0 = new Thread(producer);
Thread t1 = new Thread(producer);
//创建消费者线程
Thread t2 = new Thread(consumer);
Thread t3 = new Thread(consumer);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
/*
实现可以同时生产多个产品,可以同时消费多个产品
*/
import java.util.concurrent.locks.*;
//描述产品
class Clothes
{
//衣服名称
private String name;
// 衣服价格
private double price;
//定义一把锁
private final Lock lock = new ReentrantLock();
//定义和锁绑定的Condition对象
private final Condition pro = lock.newCondition();
//定义和锁绑定的Condition对象
private final Condition con = lock.newCondition();
//定义用来存储商品的容器
private Clothes[] arr= new Clothes[100];
//propointer生产者使用的下标,conpointer消费者使用的下标,count商品数量
private int propointer,conpointer,count;
public Clothes(){}
public Clothes(String name,double price){
this.name = name;
this.price = price;
}
//生产衣服
public void produce()
{
lock.lock();
try
{ //当商品的数量和容器的容量相同时,生产者等待
while(arr.length==count)
{
try{pro.await();}catch(InterruptedException e){e.printStackTrace();}
}
//生产产品,并放入容器中
arr[propointer] = new Clothes("羽绒服",399);
System.out.println(Thread.currentThread().getName()+"生产了..."+arr[propointer]+"=="+count);
//如果下标加1后和容器长度相同了,下标重新赋值为0
if(++propointer==arr.length)
propointer = 0;
//数量加1
count++;
//唤醒对方一个线程
con.signal();
}
finally
{
lock.unlock();
}
}
//消费衣服
public void consume()
{
lock.lock();
try
{
当商品的数量为0时,消费者等待
while(count==0)
{
try{con.await();}catch(InterruptedException e){e.printStackTrace();}
}
//从容器中取出一个商品
Clothes yifu = arr[conpointer];
System.out.println(Thread.currentThread().getName()+"....消费了..."+yifu+"===="+count);
//如果下标加1后和容器长度相同了,下标重新赋值为0
if(++conpointer==arr.length)
conpointer = 0;
//数量减1
--count;
//唤醒对方一个线程
pro.signal();
}
finally
{
lock.unlock();
}
}
public String toString()
{
return name+","+price;
}
}
//生产任务
class Producer implements Runnable
{
private Clothes clo;
public Producer(Clothes clo)
{
this.clo = clo;
}
public void run()
{
while(true)
{
clo.produce();
}
}
}
//消费任务
class Consumer implements Runnable
{
private Clothes clo;
public Consumer(Clothes clo)
{
this.clo = clo;
}
public void run()
{
while(true)
{
clo.consume();
}
}
}
class Demo6
{
public static void main(String[] args)
{
Clothes clo = new Clothes();
//创建生产任务对象
Producer producer = new Producer(clo);
//创建消费任务对象
Consumer consumer = new Consumer(clo);
//创建生产者线程
Thread t0 = new Thread(producer);
Thread t1 = new Thread(producer);
//创建消费者线程
Thread t2 = new Thread(consumer);
Thread t3 = new Thread(consumer);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
//线程的停止:stop方法已经过时,那么就只能是线程的任务代码执行完才能停止线程
//但是通常任务代码中都会有循环,所以只要让循环停止,线程就能停止
//interrupt:清除线程的等待或睡眠状态,join状态
class Test implements Runnable
{
boolean flag = true;
public synchronized void run()
{
while(flag)
{
try{wait();}
catch(InterruptedException e )
{
System.out.println("异常啦");
flag = false;
}
System.out.println(Thread.currentThread().getName()+"Hello World");
}
}
public void changeFlag()
{
this.flag = false;
}
}
class Demo7
{
public static void main(String[] args)
{
Test t = new Test();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
t2.start();
try{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();}
int i=1;
while(true)
{
if(++i==500)
{
//t.changeFlag();
t1.interrupt();
t2.interrupt();
break;
}
}
}
}
//守护线程:看成是后台线程,依赖于前台线程
class Test implements Runnable
{
boolean flag = true;
public synchronized void run()
{
while(flag)
{
try{
wait();
}
catch(InterruptedException e )
{
System.out.println("异常啦");
flag = false;
}
System.out.println(Thread.currentThread().getName()+"Hello World");
}
}
public void changeFlag()
{
this.flag = false;
}
}
class Demo8
{
public static void main(String[] args)
{
Test t = new Test();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t2.setDaemon(true);//把t2设置为守护线程,当前台线程全部执行完,守护线程即使没执行完任务代码也会结束
t1.start();
t2.start();
try{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();}
int i=1;
while(true)
{
if(++i==500)
{
//t.changeFlag();
t1.interrupt();//强制中断
//t2.interrupt();
break;
}
}
}
}
//join:让线程加入运行
class Test implements Runnable
{
public void run()
{
for(int i=1;i<=10;i++)
{
System.out.println(Thread.currentThread().getName()+"..."+i);
}
}
}
class Demo9
{
public static void main(String[] args)throws InterruptedException
{
Test t = new Test();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
//t1.join();//因为这是只有主线程和t1线程,所以主线程会等t1线程全部执行完,才和t2线程交替执行
t2.start();
t1.join();//因为有t1,t2,主线程三个线程,所以t1和t2交替执行,主线程会等t1线程全部执行完,再和t2交替执行
for(int i=1;i<=10;i++)
{
System.out.println(Thread.currentThread().getName()+"..."+i);
}
}
}
//线程池:
import java.util.concurrent.*;
class Demo10
{
public static void main(String[] args)
{
//创建只有一个线程的线程池对象,执行完一个任务才能去执行下一个任务,任务是按照被提交的顺序执行的
//ExecutorService es = Executors.newSingleThreadExecutor();
//创建固定数量线程的线程池对象--任务数量没有超过线程数量,任务会被同时执行,超过的任务会等线程池中一个执行完任务的已存在线程来执行
//ExecutorService es = Executors.newFixedThreadPool(2);
//创建一个缓存的线程池对象--会自身创建一定数量的线程,如果这个线程数超过了任务数量,会自动回收空闲的线程,当有新增加线程时
//会智能的增加线程
//ExecutorService es = Executors.newCachedThreadPool();
//创建一个数量无限制的线程池对象
ExecutorService es = Executors.newScheduledThreadPool(3);
//创建任务对象
MyTask mt1 = new MyTask();
MyTask mt2 = new MyTask();
MyTask mt3 = new MyTask();
MyTask mt4 = new MyTask();
MyTask mt5 = new MyTask();
//让线程池中的线程去执行任务
es.execute(mt1);
es.execute(mt2);
es.execute(mt3);
es.execute(mt4);
es.execute(mt5);
}
}
class MyTask implements Runnable
{
public void run()
{
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
for(int i=1;i<=10;i++)
{
System.out.println(Thread.currentThread().getName()+"---->"+i);
}
}
}
//什么时候用多线程?相同的任务需要被同时执行,或者不同的任务被同时执行
class Demo11
{
public static void main(String[] args)
{
//使用匿名内部类创建线程
new Thread(){
public void run()
{
System.out.println("haha");
}
}.start();
new Thread(new Runnable(){
public void run()
{
System.out.println("haha");
}
}).start();
Runnable r = new Runnable(){
public void run()
{
System.out.println("haha");
}
};
new Thread(r).start();
}
}
class MyThread extends Thread{
public void run()
{
try {
Thread.currentThread().sleep(3000);
} catch (InterruptedException e) {
}
System.out.println("MyThread running");
}
}
public class ThreadTest{
public static void main(String argv[])
{
MyThread t = new MyThread();
t.run();
t.start();
System.out.println("Thread Test");
}
}
/*
MyThread t = new MyThread();创建了一个线程对象,t.run()是普通的方法调用,执行run()方法中的代码,
因为当前线程只有主线程,所以是主线程先睡3秒,在主线程睡得期间程序不动了,睡够3秒后打印"MyThread running"
接下来执行 t.start()
接下来的执行有两种可能:
第一种可能:主线程仍然持有cpu,打印"Thread Test",主线程结束,这是子线程得到cpu,去执行run方法,
子线程先睡3秒,然后打印"MyThread running"
第二种可能:子线程得到cpu,执行run方法,子线程先睡3秒,睡的期间主线程得到了cpu,主线程打印"Thread Test"
然后子线程睡够了,打印"MyThread running"
*/
/*
IO流是用来处理设备之间的数据传输
IO流按照流向分为:输入流,输出流
按照流操作的数据分为:
字节流:可以操作任何类型的数据,包括文件,图片,视频,音频
Ascii ISO8859-1 gb2312 gbk utf-8
字符流:专门用来操作文本文件的,在字节流的基础上,融入了字符编码
所以说字符流是基于字节流的,就是为了方便操作文本文件
字节流:
输入流:InputStream
输出流: OutputStream
字符流:
输入流:Reader
输出流: Writer
我们最常 操作的设备是硬盘
所以我们以文件为例来讲输入输出
先使用字符流
*/
import java.io.*;
class Demo13
{
public static void main(String[] args) throws IOException
{
//往文本文件中写入数据
//因为是文本文件,所以使用字符流,又因为是写入数据,所以使用Writer,又因为是文件,所以应该使用操作文件的字符输出流
//创建文件输出流对象并和文件相关联
//如果这个文件不存在,会自动创建,否则会覆盖
FileWriter fw = new FileWriter("temp.txt");
//通过文件输出流对象把数据写入到文件
//数据写入到输出流对象内部的缓冲区了,这个缓冲区是一个字节缓冲区,目的是先查编码表,把查表结果写入到文件
fw.write("abc");
//把缓冲区中的数据刷到文件
//fw.flush();
// fw.write("ccc");//可以继续写入数据
//关闭流
fw.close();//关闭流的同时,会刷新流
//fw.write();//流已经关闭,所以不能再写入数据
}
}
import java.io.*;
class Demo14
{
public static void main(String[] args)
{
FileWriter fw = null;
try
{
fw = new FileWriter("temp.txt");//如果系统找不到指定的路径,该输出流对象就会创建失败
fw.write("abcde");
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if(fw!=null)
fw.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
//文件的续写
import java.io.*;
class Demo15
{
public static void main(String[] args)throws IOException
{
final String LINESEPARATOR = System.getProperty("line.separator");
FileWriter fw = new FileWriter("temp.txt",true);
fw.write("de");
fw.write(LINESEPARATOR);
fw.write("fg");
fw.close();
}
}
import java.io.*;
class Demo16
{
public static void main(String[] args) throws IOException
{
//读取一个文本文件 因为是一个文本文件,所以使用字符流,又因为是读,所以使用Reader,又因为是读文件,所以使用FileReader
//创建文件读取流对象和文件相关联
FileReader fr = new FileReader("temp.txt");
int num = 0;
while((num = fr.read())!=-1)
{
System.out.print((char)num);
}
fr.close();
//读取文件
/*
int num = fr.read();
System.out.println((char)num);
num = fr.read();
System.out.println((char)num);
num = fr.read();
System.out.println((char)num);
num = fr.read();
System.out.println((char)num);
num = fr.read();
System.out.println((char)num);
num = fr.read();
System.out.println(num);//-1
*/
}
}
import java.io.*;
class Demo17
{
public static void main(String[] args)throws IOException
{
FileReader fr = new FileReader("temp.txt");//abcde
char[] arr = new char[1024];
int num =0;
while((num= fr.read(arr))!=-1)
{
System.out.print(new String(arr,0,num));
}
fr.close();
/*
int num = fr.read(arr);
System.out.print(new String(arr,0,2));
num = fr.read(arr);
System.out.print(new String(arr,0,2));
num = fr.read(arr);
System.out.print(new String(arr,0,1));
num = fr.read(arr);
System.out.print(num);
*/
}
}
import java.io.*;
class Demo19
{
public static void main(String[] args)
{
FileReader fr = null;
FileWriter fw = null;
try
{
fr = new FileReader("Demo10.java");//该文件必须事先存在
fw = new FileWriter("Demo10_copy.java");
char[] arr = new char[1024];
int num = 0;
while((num = fr.read(arr))!=-1)
{
fw.write(arr,0,num);
fw.flush();
}
}
catch (IOException e)
{
throw new RuntimeException("文件读写失败");
}
finally
{
if(fr!=null)
try
{
fr.close();
}
catch (IOException e)
{
throw new RuntimeException("文件读取流关闭失败");
}
if(fw!=null)
try
{
fw.close();
}
catch (IOException e)
{
throw new RuntimeException("文件写入流关闭失败");
}
}
}
}