首页 > 编程 > Java > 正文

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

2019-11-08 19:45:08
字体:
来源:转载
供稿:网友

线程的同步

在一般情况下,创建一个线程是不能提高程序的执行效率的,所以要创建多个线程。但是多个线程同时运行的时候可能调用线程函数,在多个线程同时对同一个内存地址进行写入,由于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


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表