用跨线程访问控件持续访问某一方法

线程同时访问一个文件出现的问题
[问题点数:40分]
线程同时访问一个文件出现的问题
[问题点数:40分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。解析Java线程编程中的线程安全与synchronized的使用
作者:海子
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了Java线程编程中的线程安全与synchronized的使用,synchronized多线程使用时一定要注意线程之间的冲突问题,需要的朋友可以参考下
一.什么时候会出现线程安全问题?
  在单线程中不会出现线程安全问题,而在多线程编程中,有可能会出现同时访问同一个资源的情况,这种资源可以是各种类型的的资源:一个变量、一个对象、一个文件、一个数据库表等,而当多个线程同时访问同一个资源的时候,就会存在一个问题:
  由于每个线程执行的过程是不可控的,所以很可能导致最终的结果与实际上的愿望相违背或者直接导致程序出错。
  举个简单的例子:
  现在有两个线程分别从网络上读取数据,然后插入一张数据库表中,要求不能插入重复的数据。
  那么必然在插入数据的过程中存在两个操作:
  1)检查数据库中是否存在该条数据;
  2)如果存在,则不插入;如果不存在,则插入到数据库中。
  假如两个线程分别用thread-1和thread-2表示,某一时刻,thread-1和thread-2都读取到了数据X,那么可能会发生这种情况:
  thread-1去检查数据库中是否存在数据X,然后thread-2也接着去检查数据库中是否存在数据X。
  结果两个线程检查的结果都是数据库中不存在数据X,那么两个线程都分别将数据X插入数据库表当中。
  这个就是线程安全问题,即多个线程同时访问一个资源时,会导致程序运行结果并不是想看到的结果。
  这里面,这个资源被称为:临界资源(也有称为共享资源)。
  也就是说,当多个线程同时访问临界资源(一个对象,对象中的属性,一个文件,一个数据库等)时,就可能会产生线程安全问题。
  不过,当多个线程执行一个方法,方法内部的局部变量并不是临界资源,因为方法是在栈上执行的,而Java栈是线程私有的,因此不会产生线程安全问题。
二.如何解决线程安全问题?
  那么一般来说,是如何解决线程安全问题的呢?
  基本上所有的并发模式在解决线程安全问题时,都采用“序列化访问临界资源”的方案,即在同一时刻,只能有一个线程访问临界资源,也称作同步互斥访问。
  通常来说,是在访问临界资源的代码前面加上一个锁,当访问完临界资源后释放锁,让其他线程继续访问。
  在Java中,提供了两种方式来实现同步互斥访问:synchronized和Lock。
  本文主要讲述synchronized的使用方法,Lock的使用方法在下一篇博文中讲述。
三.synchronized同步方法或者同步块
  在了解synchronized关键字的使用方法之前,我们先来看一个概念:互斥锁,顾名思义:能到达到互斥访问目的的锁。
  举个简单的例子:如果对临界资源加上互斥锁,当一个线程在访问该临界资源时,其他线程便只能等待。
  在Java中,每一个对象都拥有一个锁标记(monitor),也称为监视器,多线程同时访问某个对象时,线程只有获取了该对象的锁才能访问。
  在Java中,可以使用synchronized关键字来标记一个方法或者代码块,当某个线程调用该对象的synchronized方法或者访问synchronized代码块时,这个线程便获得了该对象的锁,其他线程暂时无法访问这个方法,只有等待这个方法执行完毕或者代码块执行完毕,这个线程才会释放该对象的锁,其他线程才能执行这个方法或者代码块。
  下面通过几个简单的例子来说明synchronized关键字的使用:
  1.synchronized方法
  下面这段代码中两个线程分别调用insertData对象插入数据:
public class Test {
public static void main(String[] args) {
final InsertData insertData = new InsertData();
new Thread() {
public void run() {
insertData.insert(Thread.currentThread());
}.start();
new Thread() {
public void run() {
insertData.insert(Thread.currentThread());
}.start();
class InsertData {
private ArrayList&Integer& arrayList = new ArrayList&Integer&();
public void insert(Thread thread){
for(int i=0;i&5;i++){
System.out.println(thread.getName()+"在插入数据"+i);
arrayList.add(i);
  此时程序的输出结果为:
说明两个线程在同时执行insert方法。
  而如果在insert方法前面加上关键字synchronized的话,运行结果为:
class InsertData {
private ArrayList&Integer& arrayList = new ArrayList&Integer&();
public synchronized void insert(Thread thread){
for(int i=0;i&5;i++){
System.out.println(thread.getName()+"在插入数据"+i);
arrayList.add(i);
从上输出结果说明,Thread-1插入数据是等Thread-0插入完数据之后才进行的。说明Thread-0和Thread-1是顺序执行insert方法的。
  这就是synchronized方法。
  不过有几点需要注意:
  1)当一个线程正在访问一个对象的synchronized方法,那么其他线程不能访问该对象的其他synchronized方法。这个原因很简单,因为一个对象只有一把锁,当一个线程获取了该对象的锁之后,其他线程无法获取该对象的锁,所以无法访问该对象的其他synchronized方法。
  2)当一个线程正在访问一个对象的synchronized方法,那么其他线程能访问该对象的非synchronized方法。这个原因很简单,访问非synchronized方法不需要获得该对象的锁,假如一个方法没用synchronized关键字修饰,说明它不会使用到临界资源,那么其他线程是可以访问这个方法的,
  3)如果一个线程A需要访问对象object1的synchronized方法fun1,另外一个线程B需要访问对象object2的synchronized方法fun1,即使object1和object2是同一类型),也不会产生线程安全问题,因为他们访问的是不同的对象,所以不存在互斥问题。
  2.synchronized代码块
  synchronized代码块类似于以下这种形式:
synchronized(synObject) {
  当在某个线程中执行这段代码块,该线程会获取对象synObject的锁,从而使得其他线程无法同时访问该代码块。
  synObject可以是this,代表获取当前对象的锁,也可以是类中的一个属性,代表获取该属性的锁。
  比如上面的insert方法可以改成以下两种形式:
class InsertData {
private ArrayList&Integer& arrayList = new ArrayList&Integer&();
public void insert(Thread thread){
synchronized (this) {
for(int i=0;i&100;i++){
System.out.println(thread.getName()+"在插入数据"+i);
arrayList.add(i);
class InsertData {
private ArrayList&Integer& arrayList = new ArrayList&Integer&();
private Object object = new Object();
public void insert(Thread thread){
synchronized (object) {
for(int i=0;i&100;i++){
System.out.println(thread.getName()+"在插入数据"+i);
arrayList.add(i);
  从上面可以看出,synchronized代码块使用起来比synchronized方法要灵活得多。因为也许一个方法中只有一部分代码只需要同步,如果此时对整个方法用synchronized进行同步,会影响程序执行效率。而使用synchronized代码块就可以避免这个问题,synchronized代码块可以实现只对需要同步的地方进行同步。
  另外,每个类也会有一个锁,它可以用来控制对static数据成员的并发访问。
  并且如果一个线程执行一个对象的非static synchronized方法,另外一个线程需要执行这个对象所属类的static synchronized方法,此时不会发生互斥现象,因为访问static synchronized方法占用的是类锁,而访问非static synchronized方法占用的是对象锁,所以不存在互斥现象。
看下面这段代码就明白了:
public class Test {
public static void main(String[] args) {
final InsertData insertData = new InsertData();
new Thread(){
public void run() {
insertData.insert();
}.start();
new Thread(){
public void run() {
insertData.insert1();
}.start();
class InsertData {
public synchronized void insert(){
System.out.println("执行insert");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("执行insert完毕");
public synchronized static void insert1() {
System.out.println("执行insert1");
System.out.println("执行insert1完毕");
  执行结果;
第一个线程里面执行的是insert方法,不会导致第二个线程执行insert1方法发生阻塞现象。
  下面我们看一下synchronized关键字到底做了什么事情,我们来反编译它的字节码看一下,下面这段代码反编译后的字节码为:
public class InsertData {
private Object object = new Object();
public void insert(Thread thread){
synchronized (object) {
public synchronized void insert1(Thread thread){
public void insert2(Thread thread){
 从反编译获得的字节码可以看出,synchronized代码块实际上多了monitorenter和monitorexit两条指令。monitorenter指令执行时会让对象的锁计数加1,而monitorexit指令执行时会让对象的锁计数减1,其实这个与操作系统里面的PV操作很像,操作系统里面的PV操作就是用来控制多个线程对临界资源的访问。对于synchronized方法,执行中的线程识别该方法的 method_info 结构是否有 ACC_SYNCHRONIZED 标记设置,然后它自动获取对象的锁,调用方法,最后释放锁。如果有异常发生,线程自动释放锁。
有一点要注意:对于synchronized方法或者synchronized代码块,当出现异常时,JVM会自动释放当前线程占用的锁,因此不会由于异常导致出现死锁现象。
三.关于synchronized的其他一些值得注意的地方
1.synchronized与static synchronized 的区别
  synchronized是对类的当前实例进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块,注意这里是“类的当前实例”,类的两个不同实例就没有这种约束了。那么static synchronized恰好就是要控制类的所有实例的访问了,static synchronized是限制线程同时访问jvm中该类的所有实例同时访问对应的代码快。实际上,在类中某方法或某代码块中有synchronized,那么在生成一个该类实例后,该类也就有一个监视快,放置线程并发访问改实例synchronized保护快,而static synchronized则是所有该类的实例公用一个监视快了,也就是两个的区别了,也就是synchronized相当于this.synchronized,而
  static synchronized相当于Something.synchronized.
  一个日本作者-结成浩的《java多线程设计模式》有这样的一个列子:
pulbic class Something(){
  public synchronized void isSyncA(){}
  public synchronized void isSyncB(){}
  public static synchronized void cSyncA(){}
  public static synchronized void cSyncB(){}
  那么,加入有Something类的两个实例a与b,那么下列组方法何以被1个以上线程同时访问呢
  a.&& x.isSyncA()与x.isSyncB()
  b.&& x.isSyncA()与y.isSyncA()
  c.&& x.cSyncA()与y.cSyncB()
  d.&& x.isSyncA()与Something.cSyncA()
  这里,很清楚的可以判断:
  a,都是对同一个实例的synchronized域访问,因此不能被同时访问
  b,是针对不同实例的,因此可以同时被访问
  c,因为是static synchronized,所以不同实例之间仍然会被限制,相当于Something.isSyncA()与&& Something.isSyncB()了,因此不能被同时访问。
  那么,第d呢?,书上的 答案是可以被同时访问的,答案理由是synchronzied的是实例方法与synchronzied的类方法由于锁定(lock)不同的原因。
  个人分析也就是synchronized 与static synchronized 相当于两帮派,各自管各自,相互之间就无约束了,可以被同时访问。目前还不是分清楚java内部设计synchronzied是怎么样实现的。
  结论:A: synchronized static是某个类的范围,synchronized static cSync{}防止多个线程同时访问这个&&& 类中的synchronized static 方法。它可以对类的所有对象实例起作用。
  B: synchronized 是某实例的范围,synchronized isSync(){}防止多个线程同时访问这个实例中的synchronized 方法。
  2.synchronized方法与synchronized代码快的区别
  synchronized methods(){} 与synchronized(this){}之间没有什么区别,只是 synchronized methods(){} 便于阅读理解,而synchronized(this){}可以更精确的控制冲突限制访问区域,有时候表现更高效率。
  3.synchronized关键字是不能继承的
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具Java传统多线程的实现有两种方法,继承Thread类或者实现Runnable即可.线程启动时调用start()方法.
Java传统多线程的实现有两种方法,继承Thread类或者实现Runnable即可.线程启动时调用start()方法.
[摘要:完成 Runnable 接心比拟继续 Thread 类有以下优点 : 1. 幸免单继续的范围 , 一个类能够同时完成多个接心 2. 得当资本的同享 . 完成多线程摹拟卖票面卖票来讲明完成 Runnable 便可能够到达资]
实现接口相比继承类有如下好处1.避免单继承的局限一个类可以同时实现多个接口2.适合资源的共享&实现多线程模拟售票点卖票来说明实现即可可以达到资源共享的目的使用继承类的多线程售票实现650) this.width=650;" src="/uploads/u/69/c5/69c5a8ac3fa60edd461da6.gif" alt="复制代码" style="margin:0padding:0border:" />package&org.dennist.thread./** &* &*&&TicketThread.java&&&& &* &*&&@version&:&1.1 &*&& &*&&@author&&:&苏若年&&&&&a&href="mailto:"&发送邮件&/a& &*&&&& &*&&@since&&&&&:&1.0&&&&&&&&创建时间:&&&&&&&&&&&&下午02:22:49 &*&&&&& &*&&TODO&&&&&:&&&&class&TicketThread.java&is&used&for&... &*&*/public&class&TicketThreadT&extends&Thread{&&&& &&&&private&int&num&=&5;&&&&&&&&//总共票数设定为5张&&&& &&&&@Override&&&&public&void&run()&{&&&&&&&&for(int&i=0;&i&10;&i++){&&&&&&&&&&&&if(this.num&0){&&&&&&&&//打印买票信息 &&&&&&&&&&&&&&&&System.out.println(Thread.currentThread().getName()&+&"买票:&"&+&this.num--); &&&&&&&&&&&&} &&&&&&&&} &&&&}&&&& &&&&public&static&void&main(String[]&args)&{ &&&&&&&&TicketThreadT&th1&=&new&TicketThreadT();&&&&&&&&//线程一 &&&&&&&&th1.setName("售票口一");&&&& &&&&&&&&TicketThreadT&th2&=&new&TicketThreadT();&&&&&&&&//线程二 &&&&&&&&th2.setName("售票口二"); &&&&&&&&TicketThreadT&th3&=&new&TicketThreadT();&&&&&&&&//线程三 &&&&&&&&th3.setName("售票口三");&&&&&&&& &&&&&&&&//分别启动三个线程&&&&&&&&th1.start(); &&&&&&&&th2.start(); &&&&&&&&th3.start(); &&&&} }650) this.width=650;" src="/uploads/u/69/c5/69c5a8ac3fa60edd461da6.gif" alt="复制代码" style="margin:0padding:0border:" />程序运行结果:650) this.width=650;" src="/uploads/u/c3/b7/c3b7e55430cddc47c23cb1fa0152ac68.png" alt="\" style="margin:0padding:0border:0" />总共张票启动了三个线程从打印结果可以看出一共卖出去了张票线程之间没有进行资源共享实现的售票线程650) this.width=650;" src="/uploads/u/69/c5/69c5a8ac3fa60edd461da6.gif" alt="复制代码" style="margin:0padding:0border:" />package&org.dennist.thread./** &* &*&&TicketThreadR.java&&&& &* &*&&@version&:&1.1 &*&& &*&&@author&&:&苏若年&&&&&a&href="mailto:"&发送邮件&/a& &*&&&& &*&&@since&&&&&:&1.0&&&&&&&&创建时间:&&&&&&&&&&&&下午02:29:23 &*&&&&& &*&&TODO&&&&&:&&&&class&TicketThreadR.java&is&used&for&... &*&*/public&class&TicketThreadR&implements&Runnable{&&&& &&&&private&int&num&=&5;&&&&&&&&&&&&//总共票数设定为5张&&&& &&&&@Override&&&&public&void&run()&{&&&&&&&&for(int&i=0;&i&10;&i++){&&&&&&&&&&&&if(this.num&0){&&&&&&&&&&&&//打印买票信息 &&&&&&&&&&&&&&&&System.out.println(Thread.currentThread().getName()&+&"买票:&"&+&this.num--); &&&&&&&&&&&&} &&&&&&&&} &&&&}&&&&public&static&void&main(String[]&args)&{ &&&&&&&&TicketThreadR&ticketThread&=&new&TicketThreadR(); &&&&&&&& &&&&&&&&Thread&th1&=&new&Thread(ticketThread);&&&&//线程一 &&&&&&&&th1.setName("售票口一"); &&&&&&&&Thread&th2&=&new&Thread(ticketThread);&&&&//线程二 &&&&&&&&th2.setName("售票口二"); &&&&&&&&Thread&th3&=&new&Thread(ticketThread);&&&&//线程三 &&&&&&&&th3.setName("售票口三"); &&&&&&&& &&&&&&&&th1.start(); &&&&&&&&th2.start(); &&&&&&&&th3.start(); &&&&} }650) this.width=650;" src="/uploads/u/69/c5/69c5a8ac3fa60edd461da6.gif" alt="复制代码" style="margin:0padding:0border:" />程序运行结果650) this.width=650;" src="/uploads/u/3d/a8/3da85d8ebf98aa4753bd.png" alt="\" style="margin:0padding:0border:0" />虽然现在程序中有三个线程,但是三个线程总共卖出了张票也就是说使用实现的多线程可以达到资源共享的目的JRunnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做。Runnable对象,有如下两种方式来实现这些Runnable对象之间的数据共享:、将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个Runnable对象。每个线程对共享数据的操作方法也分配到那个对象身上去完成,这样容易实现针对该数据进行的各个操作的互斥和通信。、将这些Runnable对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable对象调用外部类的这些方法。、上面两种方式的组合:将共享数据封装在另外一个对象中,每个线程对共享数据的操作方法也分配到那个对象身上去完成,对象作为这个外部类中的成员变量或方法中的局部变量,每个线程的Runnable对象作为外部类中的成员内部类或局部内部类。、总之,要同步互斥的几段代码最好是分别放在几个独立的方法中,这些方法再放在同一个类中,这样比较容易实现它们之间的同步互斥和通信。static的变量,这将被所有线程共享。&&在Thread类中存在以下的几个方法可以设置和取得名字设置名字public&Thread(Runnable&target,&String&name)public&Thread(String&name)取得名字在线程的操作中因为其操作的不确定性所以提供了一个方法可以取得当前的操作线程public&static&Thread&currentThread()说明对于线程的名字一般是在启动前进行设置最好不要设置相同的名字最好不要为一个线程改名字在执行中一个程序至少启动个线程一个主线程和一个垃圾回收线程&多线程的同步问题上面的实现程序就真的没问题了吗?我们知道现实生活中买票总会有等待跟延迟那么我们模拟现实生活中的买票然后再来看上面的程序输出650) this.width=650;" src="/uploads/u/69/c5/69c5a8ac3fa60edd461da6.gif" alt="复制代码" style="margin:0padding:0border:" />package&org.dennist.thread./** &* &*&&TicketThreadR.java&&&& &* &*&&@version&:&1.1 &*&& &*&&@author&&:&苏若年&&&&&a&href="mailto:"&发送邮件&/a& &*&&&& &*&&@since&&&&&:&1.0&&&&&&&&创建时间:&&&&&&&&&&&&下午02:29:23 &*&&&&& &*&&TODO&&&&&:&&&&class&TicketThreadR.java&is&used&for&... &*&*/public&class&TicketThreadR&implements&Runnable{&&&& &&&&private&int&num&=&5;&&&&&&&&&&&&//总共票数设定为5张&&&& &&&&@Override&&&&public&void&run()&{&&&&&&&&for(int&i=0;&i&10;&i++){&&&&&&&&&&&&try&{ &&&&&&&&&&&&&&&&Thread.sleep(200);&&&&//休息200毫秒 &&&&&&&&&&&&}&catch&(InterruptedException&e)&{ &&&&&&&&&&&&&&&&e.printStackTrace(); &&&&&&&&&&&&}&&&&&&&& &&&&&&&&&&&&if(this.num&0){&&&&&&&&&&&&//打印买票信息 &&&&&&&&&&&&&&&&System.out.println(Thread.currentThread().getName()&+&"买票:&"&+&this.num--); &&&&&&&&&&&&} &&&&&&&&} &&&&}&&&&public&static&void&main(String[]&args)&{ &&&&&&&&TicketThreadR&ticketThread&=&new&TicketThreadR(); &&&&&&&& &&&&&&&&Thread&th1&=&new&Thread(ticketThread);&&&&//线程一 &&&&&&&&th1.setName("售票口一"); &&&&&&&&Thread&th2&=&new&Thread(ticketThread);&&&&//线程二 &&&&&&&&th2.setName("售票口二"); &&&&&&&&Thread&th3&=&new&Thread(ticketThread);&&&&//线程三 &&&&&&&&th3.setName("售票口三"); &&&&&&&& &&&&&&&&th1.start(); &&&&&&&&th2.start(); &&&&&&&&th3.start(); &&&&} }650) this.width=650;" src="/uploads/u/69/c5/69c5a8ac3fa60edd461da6.gif" alt="复制代码" style="margin:0padding:0border:" />650) this.width=650;" src="/uploads/u/2f/fe/2ffedb76bc518bb2cab10.png" alt="\" style="margin:0padding:0border:0" />如果想解决这样的问题就必须使用同步所谓的同步就是指多个操作在同一个时间段内只有一个线程进行其他线程要等待此线程完成之后才可以继续执行可以通过同步代码的方法进行代码的加锁操作同步的实现有中方法  1.同步代码块  2.同步方法同步代码块使用关键字进行同步代码块的声明但是在使用此操作时必须明确的指出到底要锁定的是哪个对象一般是以当前对象为主  synchronized(对象一般都是讲锁定&&&&&&&& //锁定对象&&&& }上面的问题使用同步代码块解决650) this.width=650;" src="/uploads/u/69/c5/69c5a8ac3fa60edd461da6.gif" alt="复制代码" style="margin:0padding:0border:" />package&org.dennist.thread./** &* &*&&TicketThreadR.java&&&& &* &*&&@version&:&1.1 &*&& &*&&@author&&:&苏若年&&&&&a&href="mailto:"&发送邮件&/a& &*&&&& &*&&@since&&&&&:&1.0&&&&&&&&创建时间:&&&&&&&&&&&&下午02:29:23 &*&&&&& &*&&TODO&&&&&:&&&&class&TicketThreadR.java&is&used&for&... &*&*/public&class&TicketThreadR&implements&Runnable{&&&& &&&&private&int&num&=&5;&&&&&&&&&&&&//总共票数设定为5张&&&& &&&&@Override&&&&public&void&run()&{&&&&&&&&for(int&i=0;&i&10;&i++){&&&&&&&&&&&&//使用同步代码块 &&&&&&&&&&&&synchronized&(this)&{&&&&&&&&&&&&&&&&try&{ &&&&&&&&&&&&&&&&&&&&Thread.sleep(300);&&&&//休息300毫秒 &&&&&&&&&&&&&&&&}&catch&(InterruptedException&e)&{ &&&&&&&&&&&&&&&&&&&&e.printStackTrace(); &&&&&&&&&&&&&&&&}&&&&&&&& &&&&&&&&&&&&&&&&if(this.num&0){&&&& &&&&&&&&&&&&&&&&&&&&//打印买票信息 &&&&&&&&&&&&&&&&&&&&System.out.println(Thread.currentThread().getName()&+&"买票:&"&+&this.num--); &&&&&&&&&&&&&&&&} &&&&&&&&&&&&} &&&&&&&&&&&& &&&&&&&&} &&&&}&&&&public&static&void&main(String[]&args)&{ &&&&&&&&TicketThreadR&ticketThread&=&new&TicketThreadR();&&&&&&&& &&&&&&&&new&Thread(ticketThread,"售票口一").start();&&&&//线程一 &&&&&&&&new&Thread(ticketThread,"售票口二").start();&&&&//线程二 &&&&&&&&new&Thread(ticketThread,"售票口三").start();&&&&//线程三&&&&} }650) this.width=650;" src="/uploads/u/69/c5/69c5a8ac3fa60edd461da6.gif" alt="复制代码" style="margin:0padding:0border:" />
感谢关注 Ithao123Java频道,是专门为互联网人打造的学习交流平台,全面满足互联网人工作与学习需求,更多互联网资讯尽在 IThao123!
Laravel是一套简洁、优雅的PHP Web开发框架(PHP Web Framework)。它可以让你从面条一样杂乱的代码中解脱出来;它可以帮你构建一个完美的网络APP,而且每行代码都可以简洁、富于表达力。
Hadoop是一个由Apache基金会所开发的分布式系统基础架构。
用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。
Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求,可以以流的形式访问(streaming access)文件系统中的数据。
Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,则MapReduce为海量的数据提供了计算。
产品设计是互联网产品经理的核心能力,一个好的产品经理一定在产品设计方面有扎实的功底,本专题将从互联网产品设计的几个方面谈谈产品设计
随着国内互联网的发展,产品经理岗位需求大幅增加,在国内,从事产品工作的大部分岗位为产品经理,其实现实中,很多从事产品工作的岗位是不能称为产品经理,主要原因是对产品经理的职责不明确,那产品经理的职责有哪些,本专题将详细介绍产品经理的主要职责
IThao123周刊}

我要回帖

更多关于 多线程访问同一个方法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信