Java中的线程同步跟定时任务

线程的同步

  • 在一般情况下,创建一个线程是不能提高程序的执行效率的,所以要创建多个线程。但是多个线程同时运行的时候可能调用线程函数,在多个线程同时对同一个内存地址进行写入,由于CPU时间调度上的问题,写入数据会被多次的覆盖,所以就要使线程同步。

  • 线程同步:即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态,目前实现线程同步的方法有很多,临界区对象就是其中一种。



摘自百度百科

http://baike.baidu.com/link?url=kPmqs172l-qqbYOTaCGptI1uBgBBCdPwtXldkIqNeMY6eEg_wwUjBkIPruChxZivTgSQS5xdLzO6AjEaDGs8kHLdsMwWdZ-PLM_Bx_i2W-jvg6w3zqzPjkRVF_76R6ch

同步的三种常用方法



1、同步代码块
  • 有synchronized关键字修饰的语句块



代码如:


    synchronized(object){ 
    }

被该关键字修饰的语句块会自动被加上内置锁,从而实现同步


实例:

/**
 * 线程的同步
 * @author LingDu
 */
public class Demo1 extends Thread {

    //定义一个可共享的count
    private static int count = 0;

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
                test1();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    // 默认构造函数
    public Demo1() {
        super();
    }

    // 带参数的构造函数
    public Demo1(String name) {
        super(name);
    }

    /**
     * 使用同步代码块
     */
    public void test1() {
        synchronized (Demo1.class) {
            System.out.println(Thread.currentThread().getName() + "--->" + count);
            count = count + 1;
        }
    }



    public static void main(String[] args) {
        Demo1 demo1 = new Demo1("线程1");
        Demo1 demo2 = new Demo1("线程2");
        Demo1 demo3 = new Demo1("线程3");
        Demo1 demo4 = new Demo1("线程4");

        demo1.start();
        demo2.start();
        demo3.start();
        demo4.start();
    }

}

1


2、同步方法
  • 有synchronized关键字修饰的方法

代码如:

public synchronized void save(){}

由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。

/**
 * 线程的同步
 * @author LingDu
 */
public class Demo1 extends Thread {

    //定义一个可共享的count
    private static int count = 0;

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
                test2();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    // 默认构造函数
    public Demo1() {
        super();
    }

    // 带参数的构造函数
    public Demo1(String name) {
        super(name);
    }


    /**
     * 使用同步方法
     */
    public synchronized static void test2() {
        System.out.println(Thread.currentThread().getName() + "--->" + count);
        count = count + 1;
    }

    public static void main(String[] args) {
        Demo1 demo1 = new Demo1("线程1");
        Demo1 demo2 = new Demo1("线程2");
        Demo1 demo3 = new Demo1("线程3");
        Demo1 demo4 = new Demo1("线程4");

        demo1.start();
        demo2.start();
        demo3.start();
        demo4.start();
    }
}

2




3、使用特殊域变量(volatile)实现线程同步
  • 用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。
public class Demo2 extends Thread {

    //定义一个状态,用来控制线程
    private volatile boolean sign = true;

    public boolean isSign() {
        return sign;
    }

    public void setSign(boolean sign) {
        this.sign = sign;
    }

    public Demo2() {
        super();
    }

    public Demo2(String name) {
        super(name);
    }

    @Override
    public void run() {
        // 循环10000次 ,模拟一个非常耗时的工作
        for (int i = 0; i < 10000; i++) {
            try {
                Thread.sleep(1000);
                if (sign == true) {
                    System.out.println(Thread.currentThread().getName() + "," + i);
                } else {
                    System.out.println(this.getName() + "我的状态变了,我要退出了");
                    Thread.sleep(10000);
                    break;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        // 一个名字叫main的线程
        Demo2 d1 = new Demo2();
        Demo2 d2 = new Demo2();
        d1.start();
        d2.start();
        // 让两个线程都去运行5秒
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //d1线程退出
        d1.setSign(false);
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //d2线程退出
        d2.setSign(false);

    }

}

3


Timer类


构造方法

  • Timer() 创建一个新计时器。

  • Timer(boolean isDaemon) 创建一个新计时器,可以指定其相关的线程作为守护程序运行。

  • Timer(String name) 创建一个新计时器,其相关的线程具有指定的名称。

  • Timer(String name, boolean isDaemon) 创建一个新计时器,其相关的线程具有指定的名称,并且可以指定作为守护程序运行。




常用的方法:

  • Void schedule(TimerTask task, long delay, long period) 安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。

1、 内部类的方式实现
/**
     * 创建一个定时任务
     * 内部类方式实现
     * 创建一个类TimeTaskDemo继承TimerTask,重写run方法
     */
    public static void test1(){
        //内部类方式实现
        class TimeTaskDemo extends TimerTask{

            @Override
            public void run() {
                System.out.println("1");

            }
        }
        Timer timer = new Timer();
        //schedule(TimerTask task, long delay, long period)
        // 这里的0表示立即执行 , 1000表示每1秒执行一次
        timer.schedule(new TimeTaskDemo(), 0,1000);
    }

4


2、 匿名内部类实现
/**
     * 匿名内部类实现
     */
    public static void test2(){

        Timer timer = new Timer();
        //new一个TimerTask()重写
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                System.out.println("2");

            }
        }, 0,1000);
    }

5

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值