`

java 多线程

    博客分类:
  • java
阅读更多
Java 多线程编程

Java 给多线程编程提供了内置的支持。 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。
这里定义和线程相关的另一个术语 - 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。
多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。
一个线程的生命周期
线程是一个动态执行的过程,它也有一个从产生到死亡的过程。
下图显示了一个线程完整的生命周期。


    新建状态:

    使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
    就绪状态:

    当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
    运行状态:

    如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
    阻塞状态:

    如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:

        等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。

        同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。

        其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
    死亡状态:

    一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

线程的优先级

每一个 Java 线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。

Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。

默认情况下,每一个线程都会分配一个优先级 NORM_PRIORITY(5)。

具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器资源。但是,线程优先级不能保证线程执行的顺序,而且非常依赖于平台。
创建一个线程

Java 提供了三种创建线程的方法:

    通过实现 Runnable 接口;
    通过继承 Thread 类本身;
    通过 Callable 和 Future 创建线程。

package com.test.dao;

import java.util.concurrent.*;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2018/3/16
 * Time: 11:08
 * To change this template use File | Settings | File Templates.
 */
public class Testmain {
    public static Callable getCallable(final int i,final int j){
        Callable callable = new Callable() {
            public Integer call() throws Exception {
                for(int k = 0;k<j;k++) {
                    System.out.println("callable"+i+":"+k);
                    Thread.sleep(1000);
                }
                return i;
            }
        };
        return callable;
    }
    public static void testCallable() throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<Integer> future1 = executorService.submit(getCallable(1,15));
        Future<Integer> future2 = executorService.submit(getCallable(2,20));
        System.out.println("after sumbit task");
        //如果线程1不执行玩,future1.get将停顿在此
        Integer result1 = future1.get();
        //如果线程1执行完,线程2没有执行完,future2.get()将停顿在此
        Integer result2 = future2.get();
        System.out.println("result1="+result1+",result2="+result2);
        executorService.shutdown();
    }
    public static Runnable getRunable(final int i,final int k){
        Runnable runnable = new Runnable() {
            public void run() {
                for(int j=0;j<k;j++) {
                    try {

                        System.out.println("Runnable"+i+":"+j);
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        };
        return runnable;
    }
    public static void testsubmitRunable() throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future future = executorService.submit(getRunable(1,15));
        executorService.submit(getRunable(2,20));
        //线程1执行完后才能获取get
        future.get();
        System.out.println("after:");
        executorService.shutdown();

    }
    public static void testExcuteRunable() throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();
       executorService.execute(getRunable(1,15));
        executorService.execute(getRunable(2,20));
        //不会受线程1和2的影响
        System.out.println("after:");
        executorService.shutdown();

    }
    public static void getThread(){
        Thread thread = new Thread(getRunable(1,10));
        thread.start();
        Thread thread2 = new Thread(getRunable(2,10));
        thread2.start();
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        getThread();
    }
}


创建线程的三种方式的对比

    1. 采用实现 Runnable、Callable 接口的方式创见多线程时,线程类只是实现了 Runnable 接口或 Callable 接口,还可以继承其他类。

    2. 使用继承 Thread 类的方式创建多线程时,编写简单,如果需要访问当前线程,则无需使用 Thread.currentThread() 方法,直接使用 this 即可获得当前线程。

线程的几个主要概念

在多线程编程时,你需要了解以下几个概念:

    线程同步
    线程间通信
    线程死锁
    线程控制:挂起、停止和恢复

多线程的使用

有效利用多线程的关键是理解程序是并发执行而不是串行执行的。例如:程序中有两个子系统需要并发执行,这时候就需要利用多线程编程。

通过对多线程的使用,可以编写出非常高效的程序。不过请注意,如果你创建太多的线程,程序执行的效率实际上是降低了,而不是提升了。

请记住,上下文的切换开销也很重要,如果你创建了太多的线程,CPU 花费在上下文的切换的时间将多于执行程序的时间!
多线程下java操作原子性
Atomic原子性如图:



package com.test.dao;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicMain {
    //让整数具有原子性
    private AtomicInteger count =new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        final AtomicMain atomicMain = new AtomicMain();
        //线程个数
        final CountDownLatch countDownLatch = new CountDownLatch(150);
        for(int i=0;i<150;i++){
            final int t = i;
            executorService.execute(new Runnable() {
                public void run() {
                    System.out.println(t+"="+atomicMain.count.addAndGet(1));
                    //线程数减1
                    countDownLatch.countDown();
                }
            });
        }
        //线程未执行完等待
        countDownLatch.await();
        System.out.println("结果:"+atomicMain.count);
        executorService.shutdown();
    }
}


java中实现同步加锁机制:
synchronized锁表
package com.test.dao;

public class Test1{

    private Integer count =1;
    public static void main(String[] args) {
        final Test1 test1 = new Test1();
        for(int i=0;i<10;i++){
            new Thread(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (test1.count){
                             test1.count++;

                      }
                    System.out.println(test1.count);
                }
            }).start();
        }

    }
}

ReentrantLock 锁
package com.test.dao;
import java.util.concurrent.locks.ReentrantLock;
public class Test1{
    private ReentrantLock lock = new ReentrantLock();
    private Integer count =1;
    public static void main(String[] args) {
        final Test1 test1 = new Test1();
        for(int i=0;i<10;i++){
            new Thread(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                           test1.lock.lock();
//                    synchronized (test1.count){
                             test1.count++;
                             test1.lock.unlock();

//                      }
                    System.out.println(test1.count);
                }
            }).start();
        }

    }
}

参考:http://www.runoob.com/java/java-multithreading.html
  • 大小: 38.9 KB
  • 大小: 17.7 KB
分享到:
评论

相关推荐

    Java多线程设计模式上传文件

    Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式...

    java多线程读取文件

    Java多线程读大文件 java多线程写文件:多线程往队列中写入数据

    java多线程ppt

    java多线程PPT 多线程基本概念 创建线程的方式 线程的挂起与唤醒 多线程问题

    java 多线程操作数据库

    一个java 多线程操作数据库应用程序!!!

    java多线程经典案例

    java多线程经典案例,线程同步、线程通信、线程阻塞等经典案例

    Java多线程编程技术

    《Java多线程编程核心技术》建议猿友们读两遍,因为其写得没有那么抽象,第一遍有些概念不是很理解,可以先跳过并记录起来,第一遍阅读的目的主要是了解整个架构。第二遍再慢慢品味,并贯穿全部是指点来思考,并将...

    Java多线程编程实战指南(核心篇)

    Java多线程编程实战指南(核心篇) 高清pdf带目录 随着现代处理器的生产工艺从提升处理器主频频率转向多核化,即在一块芯片上集成多个处理器内核(Core),多核处理器(Multicore Processor)离我们越来越近了――如今...

    Java多线程知识点总结

    该文档总结了Java多线程相关的知识点,分享给大家,简单易懂!

    java多线程的讲解和实战

    详细的讲解了java多线程的原理,并配有代码进行实战,适合java初学者和想对多线程有进一步了解的人。

    java多线程通信图解

    一张图方便理解和掌握java 多线程之间通信的实质 java 多线程 其实就是每个线程都拥有自己的内存空间,多线程之间的通信,比例A线程修改了主内存(main方法的线程)变量,需要把A线程修改的结果同步到主线程中,...

    java多线程处理数据库数据

    java多线程处理数据库数据,使用并发包,无框架,可批量处数据库数据,进行增删改。。等等操作。

    java多线程,对多线程,线程池进行封装,方便使用

    java多线程,对多线程,线程池进行封装,方便使用

    Java多线程编程经验

    现在的操作系统是多任务操作系统。多线程是实现多任务的一种方式。 线程是指进程中的一个执行流程,一个进程中可以运行多个线程。...本文档提供Java多线程编程经验,方便广大Java爱好者研究学习Java多线程

    java多线程处理大数据

    java多线程处理大数据,可根据配置的线程数,任务去调度处理

    java多线程并发

    java多线程并发的在新窗口

    Java多线程机制(讲述java里面与多线程有关的函数)

    Java多线程机制 9.1 Java中的线程 9.2 Thread的子类创建线程 9.3 使用Runable接口 9.4 线程的常用方法 9.5 GUI线程 9.6 线程同步 9.7 在同步方法中使用wait()、notify 和notifyAll()方法 9.8 挂起、恢复和终止线程 ...

    java多线程核心技术

    资深Java专家10年经验总结,全程案例式讲解,首本全面介绍Java多线程编程技术的专著 结合大量实例,全面讲解Java多线程编程中的并发访问、线程间通信、锁等最难突破的核心技术与应用实践 Java多线程无处不在,如...

    java多线程实现大批量数据导入源码

    java多线程实现大批量数据切分成指定份数的数据,然后多线程处理入库或者导出,线程的个数和每份数据的数量都可以控制

    java多线程查询数据库

    java多线程并发查询数据库,使用线程池控制分页,并发查询。

    java多线程模拟队列实现排队叫号

    java多线程模拟队列实现排队叫号,多线程模拟排队叫号取号 java多线程模拟队列实现排队叫号,多线程模拟排队叫号取号

Global site tag (gtag.js) - Google Analytics