多线程
来源:互联网 发布:打印机上数据没显示 编辑:程序博客网 时间:2024/05/21 06:28
public class TestCase extends junit.framework.TestCase{
//进程:正在执行中的程序,每一个进程执行都有执行的顺序,该顺序是一个执行路径或控制单元,至少有一个线程
//线程:进程中真正执行的部分,控制着进程的执行,
/*创建线程
* 1、集成Thread类,复写Thread类的run方法(Thread类中的run方法,用于存储线程要运行的代码)
* 2、实现Runable接口,覆盖run方法,通过Thread建立线程对象,将runable接口的子类对象传递给Thread的构造函数
* 调用Thread类的start方法
* 两种方法的区别
* 避免单继承的局限性(建议使用Runnable)
*
* Thread.currentThread获取当前线程对象,静态的
* */
class Thread1 extends Thread{
public void run(){
}
}
classThread2 implements Runnable{
public void run(){
}
}
/*
* 多线程的运行出现安全问题
* 问题的原因:当多条语句在操作同一个共享数据时,一个线程对多条语句只执行了一部分,就切换了另一个线程
* 解决办法:
* 对多条操作共享数据的语句,只能让一个线程都执行完,执行过程中,不让其他线程执行
* 同步代码块:锁
* synchronized(对象){
*
* }
* 同步的前提:至少两个以上的线程,多个线程使用一个锁,必须是一个线程执行
* 好处:解决了安全问题
* 弊端:消耗资源,判断锁
* 如何找问题:
* 1、明确哪些代码是多线程运行代码
* 2、明确共享数据
* 3、明确多线程运行代码中哪些语句是操作共享数据的
*
* 同步函数:public synchronized void add(){}
* 同步函数用的锁:函数需要被对象调用,那么函数都有一个所属对象引用,就是this.所以同步函数使用的就是this
* 如果同步函数被static修饰,锁不是this,因为静态方法中不可以定义this
* 静态进内存,内存中没有本类对象,但是一定有该类对应的字节码文件对象
* 类名.class 该对象的类型是class
* 静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class
*/
public void test2(){
Ticket t = new Ticket();
Thread t1 = new Thread(t,"1号窗");
Thread t2 = new Thread(t,"2号窗");
Thread t3 = new Thread(t,"3号窗");
Thread t4 = new Thread(t,"4号窗");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class DemoRun extends Thread{
//private String name;
//DemoRun(String name){
// this.name=name;
//}
DemoRun(String name){
super(name);
}
public void run(){
for(int i=0;i<50;i++)
System.out.println(Thread.currentThread().getName()+"demorun ==="+i);
}
}
class Ticket implements Runnable{
private int ticket=100;
Object ob =new Object();
public void run(){
while(true){
//同步代码快
synchronized(ob){//ob锁,线程进去,锁关闭,其他线程进不来。出去释放锁,其他线程进入
if(ticket>0){
System.out.println(Thread.currentThread().getName()+"ticket-no-"+ticket--);
}
}
}
}
}
class Tickets implements Runnable{
private int ticket=100;
Object ob =new Object();
public void run(){
while(true){
show();
}
}
//同步程序
public synchronized void show(){
if(ticket>0){
System.out.println(Thread.currentThread().getName()+"ticket-no-"+ticket--);
}
}
}
//单例(饿汉式)
class SingleOne{
private static final SingleOne s = new SingleOne();
private SingleOne(){}
public static SingleOne getInstance(){
return s;
}
}
//单例(懒汉式) 懒汉式在多线程调用时线程不安全,可采用同步解决,同步代码块(
//双重判断用的锁是该类对应的字节码文件对象)与同步函数
class SingleTwo{
private static SingleTwo s = null;
private SingleTwo(){}
public static SingleTwo getInstance(){
if(s==null){
synchronized (SingleTwo.class) {
if(s==null){
s = new SingleTwo();
}
}
}
return s;
}
}
/*
* 死锁
* 同步中嵌套同步
*/
-------------------------------------------------------------------//JDK1.5以后对锁进行了升级-----------------------------------------------------------------------
/*
* 线程间通信:
* 多个线程在操作同一个资源,但操作动作不同
*
* 等待唤醒机制
* wait notify notifyAll 都是用在同步中,因为要对持有监视器(锁)的线程操作
* 所以要使用在同步中,因为只有同步才具有锁。定义在Object中
* 等待和唤醒必须是同一把锁,锁是任意对象
*
* 当多个生产者与多个消费者 要用while循环判断,
* 用notifyAll唤醒所有线程,(会出现问题),需要生产者等待时唤醒消费者,消费者者等待时唤醒生产者
* jdk1.5后提供Lock接口,通过lock实例化Condition接口,Condition 将 Object
监视器方法(wait
、notify
和notifyAll
)分解成截然不同的对象
* 始终用的是同一把锁,不会出现死锁现象
*/
public void test1(){
//实例化资源(两个生产者,两个消费者,生产一个消费一个)
Resource r = new Resource();
new Thread(new Producer(r)).start();
new Thread(new Consumer(r)).start();
new Thread(new Producer(r)).start();
new Thread(new Consumer(r)).start();
}
}
//放进去取出来
//资源类,用于生产商品和消费商品
class Resource{
private String name;//商品名称
private int count; //商品编号
private boolean flag; //用于判断,资源类中是否有商品存在
private Lock lock = new ReentrantLock();//创建锁
private Condition condition_pro = lock.newCondition();//创建Condition 代表生产者
private Condition condition_con = lock.newCondition();//代表消费者
public void set(String name) throws InterruptedException{ //生产商品
lock.lock();//获取锁
try{
while(flag) //循环判断当资源库中有商品时,生产者等待
condition_pro.await();
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"-pro-"+this.name);
flag = true;
condition_con.signal();//唤醒消费者,消费者获得执行资格,还没有执行权,此时生产者继续进行,到上面await()那冻结
}finally{
lock.unlock(); //结束时必须将锁释放
}
}
//消费者
public void out() throws InterruptedException{
lock.lock();
try{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"-con-"+this.name);
flag = false;
condition_pro.signal();
}finally{
lock.unlock();
}
}
}
//创建生产者线程
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r=r;
}
public void run(){
while(true){
try {
r.set("打狗棒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//创建消费者线程
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r=r;
}
public void run(){
while(true){
try {
r.out();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 新手Android开发之二:onclicklistener到底怎么用?
- 控制linux动态链接库(so, standard object)导出函数
- linux本地化及国际化编程方法(配合资源文档“linux 本地化及国际化编程.pdf”学习效果更好)
- 域客士营销网站高转化的威力
- 多行转多列,行数和列数不确定
- 多线程
- 图形处理相关
- iPhone、iPad 通过网站实现一键安装 ipa 格式的 APP 应用
- 开发自己的编程语言(七)—— 字典数(相关联数组)
- 仿百度文库解决方案(五)——利用SWFTools转换PDF文档为SWF
- android 字符串分割
- android 关于网络连接之传输数据节省电量1
- 消息队列技术和原理
- windows下几个实用的快捷键