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

前段时间做了一个利用多线程解决查询大数据的功能,之前是用.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,所以这里针对的不是 该类的对象,而是该类本身。

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

时间: 2024-08-28 10:52:35

Java多线程学习与总结(一)的相关文章

java多线程学习(3)

1)竞争条件 在实际的多线程应用中,通常会有两个或多个线程需要对共同的对象进行共享访问,如果两个线程访问相同的对象,而且每一个都调用了一个会改变对象状态的方法, 那么,线程就会相互倾轧.根据各个线程访问数据的不同顺序,可能会产生腐蚀现象.这种情况通常称为竞争条件. 2)同步 为了多个线程对共享数据的腐蚀,就需要对数据的存取实现同步:常用的同步方法有3种: 1.Reenlock 用Reenlock保护代码块的基本机构如下: 1 Lock myLock=new ReenLock; 2 3 myLoc

java多线程学习(2)

1)Callable和Future Runnable封装一个异步运行的任务:可以当成一个没有任何参数和返回值的异步方法,Callable和 Runnable类似,但是它有返回值和参数. Callable接口是一个参数化的类型,只有一个方法call. 1 public interface Callable<V> 2 3 { 4 5 V call()throws Exception; 6 7 } 类型参数v是指返回值的类型,例如Callable<Integer>代表最终返回一个Inte

java多线程学习(1)

1)多线程与多进程的区别 多线程和多进程有什么区别呢?本质的区别在于每个进程有它自己的变量的完备集,线程则共享相同的数据. 对程序来说,共享的变量会使得线程之间的通信比进程间的通信更加有效和简单:同时,线程相对于进程来说,更加的“轻量级”, 线程的创建和销毁要比 进程的 开销要小的多. 2)多线程程序的构造 多线程的构造通常有两种方法, 第一种方法是,构建一个Thread的子类,并重写它的run()方法: 1 class MyThread extends Thread 2 { 3 4 publi

java多线程学习--java.util.concurrent

CountDownLatch,api 文档:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes. 假设我们要打印1-100,最

java 多线程学习(一)

1 public class ThreadA extends Thread { 2 private static int threadID = 0; 3 4 public ThreadA() { 5 super("ThreadID:" + (++threadID)); 6 } 7 8 public void run() { 9 try { 10 System.out.println(getName() + " 线程运行开始!"); 11 for (int i = 0

黑马程序员之Java多线程学习

android培训  java培训 期待与您交流! 这一篇文章主要关于java多线程,主要还是以例子来驱动的.因为讲解多线程的书籍和文章已经很多了,所以我也不好意思多说,呵呵.大家可以去参考一些那些书籍.我这个文章主要关于实际的一些问题.同时也算是我以后复习的资料吧,.呵呵大家多多指教. 同时希望多结交一些技术上的朋友.谢谢. -------------------------------------------------------------------------------------

Java多线程学习幸运飞艇采集器修复

package javastudy01; class MyThread extends Thread {//重写Run方法public void run(){//1.获取当前线程的名字System.out.println(this.getName()+"我是一个线程."); } public static void main(String[] args) {Java多线程学习幸运飞艇采集器修复,需要请搜索[大神源码论坛]dsluntan.com 客服企娥3393756370 V信170

[转]Java多线程学习(总结很详细!!!)

Java多线程学习(总结很详细!!!) 此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢? 本文主要讲java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的线程函数用法.概述等.首先让我们来了解下在操作系统中进程和线程的区别: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据空间,

Java多线程学习(吐血超详细总结)

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线程状态转换 五线程调度 六常用函数说明 使用方式 为什么要用join方法 七常见线程名词解释 八线程同步 九线程数据传递 本文主要讲了java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的一些线程函数用法.概述等. 首先讲一下进程和线程

Java多线程学习(详细)

一.进程与线程的区别 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小.(线程是cpu调度的最小单位) 线程和进程一样分为五个阶段:创建.就绪.运行.阻塞.终止.     多进程是指操作系统能同时运行多个任务(程序).     多线程是指在同一程序中有多个顺序流在执行. 在java中要想实现多线程,有两种手段,一