码迷,mamicode.com
首页 > 编程语言 > 详细

Java多线程学习与总结(一)

时间:2015-04-22 20:27:03      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

前段时间做了一个利用多线程解决查询大数据的功能,之前是用.NET写的,因工作需要,开始了解学习Java。

于是,开始去了解Java里面多线程是怎么个写法,线程同步是怎么进行的?

之前.NET里面写多线程程序,也是一知半解,并没有用到很多线程特性,只是很简单的Thread.start();

lock(obj)

{

}

来保证多个线程数据同步,甚至多个线程判断执行完毕否,还是采用 主线程

while(计数器!=0){

Thread.Sleep(100);

}

期间,线程同步问题相当让我头痛,对象集合以引用的方式在不同方法中,不同线程中的操作,更是让我心惊胆战。

最后,成功解决了大数据分表查询功能。(日后考虑贴出来,让大伙指教下)。

根据.NET版本的的代码,现在打算转换为Java版本的代码,第一直观的映像就是Java开发动不动就extends继承。

对匿名写法支持不是很好,语法确实不优雅,比较臃肿和繁琐。(8支持 拉姆达表达式了)

 

回到 多线程,首先我得知道是怎么调用的,贴一段代码(代码就找了网上的):

/**
* 使用继承java.lang.Thread类的方式创建一个线程
*
* @author DreamSea 2011-12-29 20:17:06
*/
public class ThreadTest extends Thread {

    /**
     * 重写(Override)run()方法 JVM会自动调用该方法
     */
    public void run() {
        System.out.println("I‘m running!");
    }
}

第二种,实现接口。

/**
* 通过实现Runnable接口创建一个线程
* @author DreamSea
*/
public class ThreadTest2 implements Runnable {
    public void run() {
            System.out.println("I‘m running!");
    }
}

 

需要注意下,上面ThreadTest2 类只是简单的实现了一个接口的普通类。

如果你 这样使用 new ThreadTest2().run();

根本不会在单独线程中跑,不要被它 Thread名称所迷惑,它和线程一毛关系都没有,只是一个实现普通接口的类而已。

而 ThreadTest不一样的,它继承了 Thread类,它的基类已经实现了相关线程处理方法。

new ThreadTest().start() 会以多线程的方式执行。

那么实现接口的类,如果作为多线程方式执行呢?如下:

ThreadTest2 tt = new ThreadTest2();
Thread t = new Thread(tt);
t.start();
 
好,上面了解了怎么使用。
那么多线程是个什么东西呢?和单线程有什么区别吗?
比如我们看电影,它是电脑不断重绘画面,让我们看到一种实时动画的效果。
而且,我们可以一边看电影,一边打开聊天软件聊天。感觉这些软件都是同步进行的。
这里我的理解是这样的,
每个程序占一条流水线,不同程序的指令可以同时执行。
CPU每次只能一条条的执行指令,机器周期内最多能执行 N条指令。
多核计算机机器周期内可以处理的指令会增加很多。
如果不是多线程的话,只会在CPU某核心上面一条条指令的运行。
而实际上,现在多核cpu利用率并不充分,也就是说,机器周期内可以处理的CPU指令其实可以增加很多。
单线程执行100条指令,只能一条条的执行,假设每个周期能够处理 5条指令,4核心。
100/5=20个周期时间。
如果用多线程处理,除去资源竞争等情况,周期时间内可以处理 4*5=20条指令。
100/20=5个周期时间。
这就是多核CPU用多线程程序的好处了,至于单核CPU,多线程没有任何帮助。
 
这里找了一线程状态图,感谢(http://www.cnblogs.com/DreamSea/archive/2012/01/11/JavaThread.html
 
技术分享
 
 

可以看到,线程的start()并不一定代表已经执行多线程了,start()之后,状态为 runnable(就绪状态),

然后在被 JVM调用之后,线程才会被运行。

运行过程中,可以通过 sleep(),join(),yiled(),blocked方法改变线程运行状态,又可以让线程由运行状态,改变为“暂停”状态,

然后通过相关方法,改变暂停状态为 就绪状态,等待被JVM调用继续执行。

 

这里主要了解了 object.wait()方法,和Thread.Sleep()方法。

都是将线程状态改变为暂停状态,有什么区别呢?

首先上图明确 给出, sleep方法 是 计时器来决定是否回到就绪状态以待执行的。

wairt方法 需要给接受 nofity()通知才可以继续执行。

 

要深入了解这些,必须要了解线程同步的含义了,才能明白为什么要用这些方法。

线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等。

当多个线程同时读写同一份共享资源的时候,可能会引起冲突。这时候,我们需要引入线程“同步”机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团。

线程同步的真实意思和字面意思恰好相反。线程同步的真实意思,其实是“排队”:几个线程之间要排队,一个一个对共享资源进行操作,而不是同时进行操作。

 

线程同步的方法

(1)wait():使一个线程处于等待状态,并且释放所持有的对象的lock。

(2)sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉

InterruptedException异常。

(3)notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的

唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

(4)notityAll ():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,

而是让它们竞争

 

object.wait()方法,和Thread.Sleep()

注意,这些方法都是针对线程同步的。

 

  1. private void mainLoop() {  
  2. while (true) {  
  3. ....  
  4. synchronized(queue) {  
  5. .....  
  6. if (!taskFired) // Task hasn‘t yet fired; wait  
  7. queue.wait(executionTime - currentTime);  
  8. }  
  9. }
 
  1. private void sched(TimerTask task, long time, long period) { 
  2. synchronized(queue) { 
  3. ... 
  4. queue.add(task); 
  5. }

 

如上,如果调用 wait()方法,实际就是说,当前这个线程不再阻止其他线程继续执行了,因为在 synchronized代码块中,必须代码块里面的方法全部执行完毕,才能执行下一个线程。

wait恰恰是说,好了,我还需要某些条件,你们继续执行,你们执行好了通知我就好了。主要是让出执行的权利,退出阻塞。(wait 是 object对象的基本方法,也就是作为对象锁的对象,对象锁稍后解释。)

Sleep()方法,会一直等待在那里,阻塞其他线程执行。

 

好了知道这个区别很重要,下面再回头来解释下 synchronized中的对象锁。

 

1、对于同步的方法或者代码块来说,必须获得对象锁才能够进入同步方法或者代码块进行操作;
2、如果采用method级别的同步,则对象锁即为method所在的对象,如果是静态方法,对象锁即指method所在的
Class对象(唯一);
3、对于代码块,对象锁即指synchronized(abc)中的abc;

 

那么我们看看这些 锁对象:

String lock=new String(“”);

 

Threada{

  private String lock;

PUBLIC (String lock){lock=lock;}

 

run(){

synchronized(lock){

 

}

}

}

 

main(){

String lockObj=new String(“lock”);

new Threada(lockObj).start();

new Threada(lockObj).start();

new Threada(lockObj).start();

}

 

在java 中,lockObj是值引用,而且这里是 主线程中的对象,所以各个 线程实际上锁对象是同一个,是main方法里面的 lockObj对象。

 

static synchronized run(){

 

}

这里 synchronized 引用的是这个方法的对象本身,因为设置了 static,所以这里针对的不是 该类的对象,而是该类本身。

 

好了,下班了,基本概念厘清了。

Java多线程学习与总结(一)

标签:

原文地址:http://www.cnblogs.com/mophes/p/4448303.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!