`
badpie
  • 浏览: 5545 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

Java Code之线程与同步(一)

阅读更多

模拟一个实例,用一个线程负责写数据,一个线程负责读数据,清单如下:

FileManager.java 负责读和写的具体实现
Main.java 主类,入口
TaskThread.java 自定义线程类
TaskRead.java 读任务
TaskWrite.java 写任务

 

FileManager.java

package com.iteye.badpie.javacode.thread.sync;

import java.util.Random;

public class FileManager {

    private Random mRandom;
    private String mName = "默认名字";
    private String mEmail = "默认电子邮件";

    public FileManager() {
        mRandom = new Random();
    }

    public void write(String id, String name, String email) {
        mName = name;
        try {
            Thread.sleep(getRandomInt());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        mEmail = email;
        System.out.println(String.format("写数据 id:%s, name:%s, email:%s", id, name, email));
    }

    public void read(String id) {
        try {
            Thread.sleep(getRandomInt());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(String.format("读数据 id:%s, name:%s, email:%s", id, mName, mEmail));
    }

    private int getRandomInt() {
        return mRandom.nextInt(2000);
    }

}

 

Main.java

package com.iteye.badpie.javacode.thread.sync;

import com.iteye.badpie.javacode.thread.sync.TaskThread.ITask;

public class Main {

    public static void main(String[] args) {
        System.out.println("主线程开始运行");

        FileManager fileManager = new FileManager();
        ITask taskWrite = new TaskWrite("w", fileManager);
        ITask taskRead = new TaskRead("r", fileManager);

        new TaskThread(taskWrite).start();
        new TaskThread(taskRead).start();

        System.out.println("主线程运行结束");
    }

}

 

TaskThread.java

package com.iteye.badpie.javacode.thread.sync;

public class TaskThread extends Thread {

    private ITask mTask;

    public TaskThread(ITask task) {
        mTask = task;
    }

    @Override
    public void run() {
        mTask.execute();
    }

    public interface ITask {
        public void execute();
    }

}
 

TaskRead.java

package com.iteye.badpie.javacode.thread.sync;

import com.iteye.badpie.javacode.thread.sync.TaskThread.ITask;

public class TaskRead implements ITask {

    private String mId;
    private FileManager mFileManager;

    public TaskRead(String id, FileManager fileManager) {
        mId = id;
        mFileManager = fileManager;
    }

    @Override
    public void execute() {
        for (int i = 0; i < 5; i++) {
            mFileManager.read(mId);
        }
    }

}

 

TaskWrite.java

package com.iteye.badpie.javacode.thread.sync;

import com.iteye.badpie.javacode.thread.sync.TaskThread.ITask;

public class TaskWrite implements ITask {

    private String mId;
    private FileManager mFileManager;

    public TaskWrite(String id, FileManager fileManager) {
        mId = id;
        mFileManager = fileManager;
    }

    @Override
    public void execute() {
        for (int i = 0; i < 5; i++) {
            mFileManager.write(mId, i + "的名字", i + "的电子邮件");
        }
    }

}

 

某一次运行结果如下

主线程开始运行
主线程运行结束
写数据 id:w, name:0的名字, email:0的电子邮件
读数据 id:r, name:1的名字, email:0的电子邮件
写数据 id:w, name:1的名字, email:1的电子邮件
读数据 id:r, name:2的名字, email:1的电子邮件
读数据 id:r, name:2的名字, email:1的电子邮件
写数据 id:w, name:2的名字, email:2的电子邮件
读数据 id:r, name:3的名字, email:2的电子邮件
写数据 id:w, name:3的名字, email:3的电子邮件
读数据 id:r, name:4的名字, email:3的电子邮件
写数据 id:w, name:4的名字, email:4的电子邮件

  分析一下结果,有明显的问题,写数据时,0的名字和0的电子邮件,1的名字和1的电子邮件等等,他们是一一对应的,但是在第一次读数据时就出现了数据错误,竟然把1的名字和0的电子邮件配对了。

可能导致此问题的原因是:在写数据时,当前数据只写了一半,就有读操作产生,于是就将本次的前半段数据(比如1的名字)和上一次的后半段数据(比如0的电子邮件)配对了。

解决此问题的方法是对写和读做同步,意思是说当我在写数据时就不允许读,在读数据时,不允许写,这样每次写或者读总是能够保证数据是统一的,配对是正确的。

java中的每一个实例对象都有一个锁,称之为lock,就像这样的场景:数据在屋子里,门上有一把锁,读数据的人和写数据的人都在门外排队,一个人进屋就将门反锁住,他读或者写完毕了打开门出来,再让下一个人进屋,这个人再将们反锁住,于是,这就能保持屋子里的数据始终是配对的,不会将第一个人的一半数据和第二个人的一半数据配对。

实现方式如下:

只需要对此处的FileManager做一个小小的改动就可以了(由synchronized关键字负责锁门)

package com.iteye.badpie.javacode.thread.sync;

import java.util.Random;

public class FileManager {

    private Random mRandom;
    private String mName = "默认名字";
    private String mEmail = "默认电子邮件";
    private Object mLock;

    public FileManager() {
        mRandom = new Random();

        // 实例化一个锁
        mLock = new Object();
    }

    public void write(String id, String name, String email) {

        // 锁门
        synchronized (mLock) {
            mName = name;
            try {
                Thread.sleep(getRandomInt());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            mEmail = email;
            System.out.println(String.format("写数据 id:%s, name:%s, email:%s", id, name, email));
        }
        // 打开门

    }

    public void read(String id) {

        // 锁门
        synchronized (mLock) {
            try {
                Thread.sleep(getRandomInt());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(String.format("读数据 id:%s, name:%s, email:%s", id, mName, mEmail));
        }
        // 打开门

    }

    private int getRandomInt() {
        return mRandom.nextInt(2000);
    }

}

再次执行,结果如下:

主线程开始运行
主线程运行结束
读数据 id:r, name:默认名字, email:默认电子邮件
读数据 id:r, name:默认名字, email:默认电子邮件
读数据 id:r, name:默认名字, email:默认电子邮件
读数据 id:r, name:默认名字, email:默认电子邮件
读数据 id:r, name:默认名字, email:默认电子邮件
写数据 id:w, name:0的名字, email:0的电子邮件
写数据 id:w, name:1的名字, email:1的电子邮件
写数据 id:w, name:2的名字, email:2的电子邮件
写数据 id:w, name:3的名字, email:3的电子邮件
写数据 id:w, name:4的名字, email:4的电子邮件

 上面的锁也可以这样挂:

package com.iteye.badpie.javacode.thread.sync;

import java.util.Random;

public class FileManager {

    private Random mRandom;
    private String mName = "默认名字";
    private String mEmail = "默认电子邮件";

    public FileManager() {
        mRandom = new Random();
    }

    public void write(String id, String name, String email) {

        // 锁门 对当前实例挂锁
        synchronized (this) {
            mName = name;
            try {
                Thread.sleep(getRandomInt());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            mEmail = email;
            System.out.println(String.format("写数据 id:%s, name:%s, email:%s", id, name, email));
        }
        // 打开门

    }

    public void read(String id) {

        // 锁门
        synchronized (this) {
            try {
                Thread.sleep(getRandomInt());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(String.format("读数据 id:%s, name:%s, email:%s", id, mName, mEmail));
        }
        // 打开门

    }

    private int getRandomInt() {
        return mRandom.nextInt(2000);
    }

}

 还可以这样挂锁:

package com.iteye.badpie.javacode.thread.sync;

import java.util.Random;

public class FileManager {

    private Random mRandom;
    private String mName = "默认名字";
    private String mEmail = "默认电子邮件";

    public FileManager() {
        mRandom = new Random();
    }

    public synchronized void write(String id, String name, String email) {
        mName = name;
        try {
            Thread.sleep(getRandomInt());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        mEmail = email;
        System.out.println(String.format("写数据 id:%s, name:%s, email:%s", id, name, email));
    }

    public synchronized void read(String id) {
        try {
            Thread.sleep(getRandomInt());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(String.format("读数据 id:%s, name:%s, email:%s", id, mName, mEmail));
    }

    private int getRandomInt() {
        return mRandom.nextInt(2000);
    }

}

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    Java code Java code

    在给定的信息中,我们可以看到一系列与Java编程相关的文件,标题和描述中虽然没有具体的代码内容,但通过标签"Java code"我们可以推断这是一组关于Java编程的源代码文件。下面,我们将根据常见的Java编程知识点,...

    java基础,javacode

    Java是一种广泛使用的面向对象的编程语言,以其跨平台性、高效性和丰富的类库而闻名。在Java编程中,"Java代码"通常指的是用Java语言编写的程序或脚本。在这个主题下,我们将深入探讨Java的基础知识,包括语法、类、...

    Java Thread Programming (Sams) java线程编程(含code)

    4. **线程同步** - `synchronized`关键字:用于方法或代码块,确保同一时刻只有一个线程执行。 - `volatile`关键字:保证变量在所有线程间可见,防止指令重排序。 - `wait()`, `notify()`, `notifyAll()`:在同步...

    多线程并行执行,汇总结果

    `CountDownLatch`是Java并发包(java.util.concurrent)中的一个计数器类,它允许一个或多个线程等待其他线程完成操作。在初始化时,`CountDownLatch`需要一个非负整数作为计数器的初始值。每次调用`countDown()`...

    java_code.rar_java code

    多线程是Java的一大特色,Java代码实例会展示如何创建线程、同步机制(如synchronized关键字、Lock接口)、线程池的使用,以及并发工具类(如CountDownLatch、CyclicBarrier、Semaphore等)的应用。 网络编程是Java...

    JAVA code example 100 例

    在本资源"JAVA code example 100 例"中,我们拥有一系列精心挑选的Java编程示例,旨在帮助开发者深入理解和应用Java语言。这个压缩包包含了从基础到高级的100个源代码实例,覆盖了Java编程的多个重要方面。下面,...

    core java source code

    2. **并发编程**:详细讨论了线程、同步机制、并发工具类,如Semaphore、CyclicBarrier等,以及如何处理线程安全问题。 3. **网络编程**:涵盖了套接字编程,客户端-服务器模型,以及相关的网络API。 4. **GUI编程**...

    corejava_code

    1. **基础语法**:Java是一种面向对象的编程语言,其基础语法包括变量声明、数据类型(如int, String等)、运算符(如赋值、比较、逻辑等)、控制结构(if语句、for循环、while循环)、方法定义与调用。 2. **类与...

    支持断点续传java多线程下载.doc

    在多线程下载中,线程同步是关键,以确保数据的正确合并。这通常通过共享对象(如`DownInfo`类中的`startPos`和`endPos`)和适当的同步机制(如`synchronized`关键字或`Lock`接口)来实现,防止不同线程同时修改...

    java-code Java语言程序.zip

    Java编程语言是世界上最流行的开发平台之一,以其跨平台、面向对象和安全性著称。这个名为"java-code Java语言程序.zip"的压缩包很可能是包含了一系列的Java源代码文件,供学习、参考或直接使用。在Java编程中,我们...

    Java多线程与线程安全实践-基于Http协议的断点续传

    在Java中,我们可以使用`synchronized`关键字或者`java.util.concurrent`包下的工具类来实现线程同步,防止数据竞争。例如,可以使用`synchronized`方法或代码块来控制对共享资源的访问,确保同一时间只有一个线程...

    java实例手册Codesamples

    《Java实例手册Codesamples》是SUN公司发布的一份详细且实用的编程资源,主要针对Java编程语言。这本书籍包含了丰富的代码示例,旨在帮助开发者深入理解和应用Java技术。以下是一些关键知识点的概述: 1. **Java...

    线程同步与异步套接字编程

    在计算机编程领域,尤其是网络编程中,线程同步与异步套接字编程是至关重要的概念,它们直接影响到程序的性能、稳定性和可扩展性。本文将深入探讨这两个主题,并结合实际应用进行详细阐述。 首先,我们需要理解线程...

    Java 创建线程的例子

    在实际开发中,合理使用线程和线程同步技术可以提升程序性能,同时保证程序的正确性和稳定性。本示例提供的代码可能包含了这些概念的应用,具体实现需查看解压后的`codefans.net`文件以获取更多信息。

    java system code

    理解和掌握线程同步机制,如`synchronized`关键字、`wait()`, `notify()`和`notifyAll()`方法,以及`Lock`接口,是编写高效并发程序的关键。 6. **异常处理**: Java的异常处理机制通过`try-catch-finally`块来捕获...

    Java并发:基础线程同步

    3.Using conditions in synchronized code; 4.Synchronizing a block of code with a Lock; 5.Synchronizing data access with read/write locks 6.Modifying Lock fairness 7.Using multiple conditions in a Lock

    jibu_java_1.0.0.zip_Parallel Java Code_java1.0.0_jibu_java_1.0.0

    本资源"jibu_java_1.0.0.zip"提供了一个名为"jibu_java_1.0.0"的Java并行编程库,它专为Java 1.0.0设计,旨在帮助开发者高效地编写多线程、多核并行的程序。 并行编程是将一个大型任务分解成若干个可以同时执行的小...

Global site tag (gtag.js) - Google Analytics