Android之JAVASe基础篇-面向对象-多线程(七)

一、进程与线程
进程是程序的一次动态执行过程,它经历了从代码加载、执行到执行完毕的一个完整的过程,这个过程也是进错本身从产生、发展到最终消亡的过程。
多线程是实现并发机制的一种有效的手段。进错和线程一样,都是实现并发的一个基本单位。
实现多线程的2种方式:
1.继承Thread类
2.实现Runnable接口

import java.lang.*;
class MyThread extends Thread
{
    private int ticket=5;   //5张票要卖出去
    public void run(){  //必须覆写run()方法,作为线程的操作主体
        for(int i=0;i<100;i++){
            if(this.ticket>0){
                System.out.println("卖票:ticket="+ticket--);
            }
        }
    }
}
class MyRunnable implements Runnable
{
    private int ticket=5;
    public void run(){
        for(int i=0;i<100;i++){
                if(this.ticket>0){
                System.out.println("卖票:ticket="+ticket--);
            }
        }
    }
}
public class TreadDemo
{
    public static void main(String[] args)throws Exception{
        MyThread mt1=new MyThread();
        MyThread mt2=new MyThread();
        MyThread mt3=new MyThread();
        /*System.out.println("***MyThread线程1卖票***");
        mt1.run();
        System.out.println("***MyThread线程2卖票***");
        mt2.run();
        System.out.println("***MyThread线程3卖票***");
        mt3.run();*/
        mt1.run();


        MyRunnable mr1=new MyRunnable();
        System.out.println("***MyRunnable线程1卖票***");
        new Thread(mr1).run();

        new Thread(mr1).run();

        new Thread(mr1).run();

    }
}

继承Thread类:继承Thread类,此类就称为多线程操作类。在Thread子类之中,必须明确的覆写Thread类中的run()方法,此方法为线程的主体。

class MyThread extends Thread{
    属性。。;
    方法。。。;
        public void run(){//覆写Thread类中的run()方法
        线程主体;
    }
}
public class Test{
    public static void main(String[] args) throws Exception{
        MyThread mt=new MyThread();
        mt.start();
    }
}

二、线程的使用和同步
同步很重要的;
问题:以卖火车票为例,如果现在是要想买火车票,可以在网上买或者各个售票点买,但是不管有多少个地方可以买,最终一趟列车的车票数量是固定的,如果把各个售票点理解成为各个线程的话,则所有的线程应该共同拥有同一份的票数。
如下面的代码:

class MyRunnable implements Runnable
{
    private int ticket=5;
    public void run(){
        for(int i=0;i<100;i++){
        if(this.ticket>0){
                try{
                    Thread.sleep(300);
                }catch(Exception e){
                    e.printStackTrace();
                }
                System.out.println("卖票:ticket="+ticket--);
            }
        }
    }
    }

public class TreadDemo2
{
    public static void main(String[] args)throws Exception{
        MyRunnable mt=new MyRunnable();
        Thread t1=new Thread(mt);
        Thread t2=new Thread(mt);
        Thread t3=new Thread(mt);
        t1.start();
        t2.start();
        t3.start();
    }
}
//注:程序运行的结果会出现 ticket=-1的情况。
原因:分析:以上程序有 1.判断票数是否大于0,大于0则表示还有票可以卖。
    2.如果票数大于0,则买票出去
但是,上面的操作中第1步和第二步之间加入了延迟操作,那么一个线程就有可能在还没有对票数进行减操作之前,其他线程就已经将票数减少了,这样依赖就会出现票数为负的情况。

解决方法:使用同步,所谓同步就是指多个操作在同一个时间段内只能有一个线程进行,其他线程要等待此线程完成之后才可以继续执行。
要想解决资源共享的同步操作问题,可以使用同步代码块及同步方法两中方式完成。
1.同步代码块(使用synchronized关键字声明的代码块)
格式:synchronized(同步对象){
需要同步的代码;
}
同步的时候必须指明同步的对象,一般情况下将当前对象作为同步的对象,使用this表示。

class MyRunnable implements Runnable
{
    private int ticket=5;
    public void run(){
        for(int i=0;i<100;i++){
        synchronized(this){    //synchronied同步
            if(this.ticket>0){
                    try{
                        Thread.sleep(500);
                    }catch(Exception e){
                        e.printStackTrace();
                    }
                    System.out.println("卖票:ticket="+ticket--);
                }
        }
        }
    }
    }

public class TreadDemo2
{
    public static void main(String[] args)throws Exception{
        MyRunnable mt=new MyRunnable();
        Thread t1=new Thread(mt);
        Thread t2=new Thread(mt);
        Thread t3=new Thread(mt);
        t1.start();
        t2.start();
        t3.start();
    }
}
//注意:这种方法效率明显会降低。

2.同步方法
前面是同步代码块,也可以是用synchronized关键字将一个方法声明成同步方法。
格式:
synchronized 方法返回值 方法名称(参数列表){}

}

public class TreadDemo2
{
    public static void main(String[] args)throws Exception{
        MyRunnable mt=new MyRunnable();
        Thread t1=new Thread(mt);
        Thread t2=new Thread(mt);
        Thread t3=new Thread(mt);
        t1.start();
        t2.start();
        t3.start();
    }
}

四、多线程案例:生产者与消费者
问题:生产一个取走一个

package com.test;
import java.lang.*;
class Info{
    private String name="初始姓名";
    private String content="初始内容";
    private boolean flag=false;
    public synchronized void set(String name,String content) throws InterruptedException{
        if(!flag){
            super.wait();
        }
        this.setName(name);
        Thread.sleep(300);
        this.setContent(content);
        flag=false;
        super.notify();//唤醒线程
    }
    public synchronized void get() throws InterruptedException{
        if(flag){
            super.wait();
        }
        Thread.sleep(300);
        System.out.println("姓名:"+this.getName()+'\t'+"内容:"+this.getContent());
        flag=true;  //改变flag,表示已经取走可以生产
        super.notify();//唤醒
    }


    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
}
class Producer implements Runnable{
    private Info info=null;
    public Producer(Info info){
        this.info=info;
    }
    public void run(){
        boolean flag=false;//定义标记位
        for(int i=0;i<10;i++){
            if(flag){
                try {
                    System.out.print("生成1="+i+'\t');
                    this.info.set("张三", "男的");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                flag=false;
            }else{
                try {
                    System.out.print("生成2="+i+'\t');
                    this.info.set("abcd", "abcdefg");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                flag=true;
            }
        }
    }
}
class Consumer implements Runnable{
    private Info info=null;
    public Consumer(Info info){
        this.info=info;
    }
    public void run(){
        for(int i=0;i<10;i++){
            try {
                System.out.print("取走="+i+'\t');
                this.info.get();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
public class ThreadTestDemo01 {
    public static void main(String[] args){
        Info info=new Info();
        Producer pro=new Producer(info);
        Consumer con=new Consumer(info);
        new Thread(pro).start();
        new Thread(con).start();
    }
}

注:上面的代码完成了生成一个取走一个。
细细研究的时候还请大家多看看书才行哦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值