JavaSE复习_10 多线程复习

wait()和sleep()的区别:

 1.wait():没有等待时间,而sleep()需要有等待时间作为参数。

 2.在同步中对于CPU的执行权和锁的处理不同:

  wait()会释放执行权和锁.醒来后需要重新竞争锁.

  sleep():释放执行权和,不会释放锁

void show(){
     Synchronized(this){
          wait()          //可以同时有三个线程在此等待。只有拿到锁后,才能继续向下运行
}
}
void start(){
     notifyAll();     //唤醒后,三个线程都具备了执行资格,但是并不是都具备执行权。
}

△interupt:可以通过interrupt强制将线程从冻结状态强制执行,但是会发生异常需要处理。

当一个线程调用interrupt方法的时候,线程的中断状态将被置位.这是每一个线程都具备的boolean标志,每个线程都可以去检查这个标志,判断当前线程是否被中断(通过isInterrupted方法判断).如果线程被阻塞,(如wait和sleep的线程),此时调用interrupt方法,阻塞调用会被InterruptedException异常中断.如果在中断状态的时候调用sleep方法,将不会休眠,相反将清除中断状态,并且抛出InterruptedException异常.一个实例:

public class Interrupted {
    public static void main(String[] args) {
        Task t=new Task();
        Thread t1=new Thread(t);
        t1.start();
    }
}
class Task implements Runnable {

    @Override
    public void run() {
        for (int i=0;i<50;i++) {
            if(i==30)
                Thread.currentThread().interrupt();
            System.out.println(Thread.currentThread().isInterrupted()+""+i);
        }
    }
}

输出:

false0
false1
false2
false3
false4
false5
false6
false7
false8
false9
false10
false11
false12
false13
false14
false15
false16
false17
false18
false19
false20
false21
false22
false23
false24
false25
false26
false27
false28
false29
true30
true31
true32
true33
true34
true35
true36
true37
true38
true39
true40
true41
true42
true43
true44
true45
true46
true47
true48
true49

△setDaemon:将线程设置为守护线程(后台线程),此时当虚拟机只剩下守护线程在运行时,守护线程将停止运行。

△join:对于线程调用join方法,会使当前线程暂时释放执行权,值到申请加入的线程执行完毕后,该线程才会运行。

△setPriority:设置线程的优先级

△public static void yield():礼让线程,让出CPU的执行权.如果有其他的可运行线程具有至少与此线程同样高的优先级,那么这些线程接下来将会被调度

△Lock.newCondition:将获取条件变量,一个锁可以有一个或多个相关的条件对象.await方法,将线程放在条件的等待集中,而signalAll方法将会解除该条件的等待集中的所有现场的阻塞状态.

△notifyAll,wait,notify方法只能在同步方法和同步代码块中使用

△volatile为实例域的同步实现了一种免锁机制,如果声明一个域为volatile,则编译器和虚拟机就知道该域是可能被另一个线程并发更新的.因此变量的更新操作能立即通知到其他线程,新值能立即同步到主内存.

△可以通过ThreadLocal辅助类为每个线程构建一个自己的实例:

可以使用下面的代码:

public static final ThreadLocal<SimpleDateForamt> dateFormat=new ThreadLocal<SimpleDateForamt>() {
     protected SimpleDateFormat initialValue() {
          return new SimpleDateFormat("yyyy-MM-dd");
     }
}

当在一个给定的线程中首次调用get方法的时候会掉用initialValue方法,在此之后,get方法会返回当前线程的实例.

判断是否会出现线程安全的问题,一定要看两点:第一,有无共享的被所有现场所操作的数据,第二,操作会不会产生安全隐患.

△线程在调用lock()方法去试图获得锁的时候,有可能发生阻塞,tryLock方法试图申请一个锁,在成功获得锁后返回true,否则立即返回false,当前线程可以立即离开去做其他的事情.

boolean tryLock(long time,Timeunit unit):尝试获取锁,阻塞时间不会超过给定的值,如果成功返回true.

await方法中也可以提供参数,await(long time,Timeunit unit):如果超时的时间到了,则解除阻塞

△Java.util.concurrent.locks定义了另外一个锁,读写锁,可以获得可以被多个读取线程所共用(但是排斥写操作)的读锁.和排斥其他所有操作的写锁.方法如下:

private ReentrantReadWriteLock rwl=new ReentrantReadWriteLock();
Private Lock readLock=rwl.readLock();          //读取操作共享,排斥写操作
private Lock writeLock=rwl.writeLock();        //排斥所有其他操作

△stop方法被停止使用,因为无法知道什么时候调用stop方法是安全的,什么时候导致对象被破坏.在希望停止线程的时候应该中断线程,被中断的线程会在安全的时候停止.(采用inInterrupted判断).

△Callerable与Runnable类似,但是内部的方法有返回值.类型参数是返回值的类型.Future可以保存异步计算的结果,FutureTask包装器是一种很便利的机制,可以将Callable转换成Future和Runnable,它同时实现两者的接口.例如:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
* Created by Administrator on 2016/6/30.
*/
public class Exercise {
    public static void main(String[] args) {

        FutureTask<Integer> task=new FutureTask<Integer>(new Counter());    //包装Callable
        Thread t=new Thread(task);
        t.start();  //这是Runnable接口的特性
        try {
            System.out.println(task.get());    //这是Future接口的特性
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}
class Counter implements Callable<Integer> {
    int sum;
    @Override
    public Integer call() throws Exception {
        for (int i=0;i<100;i++) {
            sum+=i;
        }
        return sum;
    }
}

△ExecutorService newCashedThreadPool():返回一个带缓存的线程池,该池在必要的时候创建线程.

ExecutorService newFixedThreadPool(int threads):返回一个线程池,该池中的线程数由参数的指定,超出参数的线程将放入处理队列中.

ExecutorService newSingleThreadExecutor():返回一个执行器,它在一个和单个的线程中依次执行各个任务.

线程池可以调用submit提交需要执行的任务,将返回一个Future对象.可以用于取消对象.如果线程池提交的任务是Callable类型的任务可以利用返回的Future对象调用get方法获得值.

使用连接线程池时候应该做的事情:

1)调用Executors类中的静态方法newCachedThreadPool或newFixedThreadPool.

 2)调用submit提交Runnable和Callable对象

 3)如果想要取消一个任务或者想要获取Callable对象的值,就要保存好返回的Future对象.

 4)若不再提交任何任务的时候,调用shutdown.

简单示例:

  

        // public static ExecutorService newFixedThreadPool(int nThreads)
        ExecutorService pool = Executors.newFixedThreadPool(2);

        // 可以执行Runnable对象或者Callable对象代表的线程
        Future fu1=pool.submit(new MyRunnable());
        Future fu2=pool.submit(new MyCallable());
        fu1.cancel();//取消该任务
        System.out.println(fu2.get());//获取Callable对象的运行结果
        //结束线程池
        pool.shutdown();
时间: 2024-10-13 01:39:58

JavaSE复习_10 多线程复习的相关文章

Android学习之多线程复习——倒计时

今天周六,离职在家,复习了一下多线程的一些知识 然后写了一个简单的倒计时程序: 以下是我的activity_main的布局文件: 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent&q

多线程复习

OS看到进程管理这一章,对进程.线程的理解又加深了一层,考研这段时间好久没写代码,复习一下线程,一个小demo: package threadone; public class ThreadTest { public static void main(String[] args) { HelloRunner r1=new HelloRunner("r1 "); HelloRunner r2=new HelloRunner("r2 "); HelloRunner r3

多线程复习笔记

1. 多线程是什么?         线程就是程序中单独顺序的流控制.线程本身不能运行,它只能用于程序中.多线程则指的是在单个程序中可以同时运行多个不同的线程执行不同的任务. 2. 为什么使用多线程? 多线程编程的目的,就是"最大限度地利用CPU资源",当某一线程的处理不需要占用CPU,而只和I/O等资源打交道时,让需要占用CPU资源的其它线程有机会获得CPU资源. 3. 线程与进程有什么不同? 1). 资源是否独立:多个进程的内部数据和状态都是完全独立的,而多线程是共享一块内存空间和

[Java]多线程复习(更新未完)

知识点小结:(具体看例子) 多线程: 线程是程序中单独创建的控制单元,是并发执行的程序.外部顺序执行的程序叫做主线程. 线程是多任务操作系统调用CPU来回切换的程序. 注意:线程开启要用start方法,虚拟机调用底层向操作系统申请一个单独线程.如果你只执行run方法, 那么并没有开启一个线程,仅仅是一个普通类的方法,那么是在主线程中顺序执行的.你开启start是虚 拟机新开启一个线程后自动去调用run方法的. Windows执行虚拟机,虚拟机执行多线程程序,多线程程序调用底层Windows,最终

Java基础复习(2) 多线程相关 sleep() yield() wait() join()等方法简略说明

2015-10-23 今天回顾的是多线程的部分,对于线程编程常用的几个方法稍作整理和区分. 1.join方法 (之前总是记的迷迷糊糊,重新看了一遍,算是基本理清了orz) join方法属于线程,意思是把指定线程加入到当前线程执行序列,可以让本来是交替执行的两个线程合并成顺序执行的线程.例如:同时执行线程thread-A和线程thread-B,此时在线程thread-B中调用线程thread-A的join()方法,结果就是直到线程thread-A执行完毕,线程thread-B才继续执行. 使用:

[Java复习05] 多线程&amp;并发 知识点补充

0. wait/notify/notifyAll的理解? wait:让持有该对象锁的线程等待: notify: 唤醒任何一个持有该对象锁的线程: notifyAll: 唤醒所有持有该对象锁的线程: 它们 3 个的关系是,调用对象的 wait 方法使线程暂停运行,通过 notify/ notifyAll 方法唤醒调用 wait 暂时的线程. 它们并不是 Thread 类中的方法,而是 Object 类中的,为什么呢? 因为每个对象都有监视锁,线程要操作某个对象当然是要获取某个对象的锁了,而不是线程

[期末复习] 计算机操作系统复习(一)

操作系统期末复习 第一章-操作系统引论 操作系统的作用 作为计算机硬件系统之间的接口 系统资源的管理者 实现对计算机资源的抽象 操作系统的发展过程 未配置操作系统的计算机系统 人工操作,用户独占全机,资源浪费 脱机输入输出(Off-Line I/O)方式. 单道批处理系统 这里批处理指的是把很多作业放在一个磁带上,一次性输入给计算机 解决了人机矛盾(每执行一道程序都要手动装载)和cpu与I/O设备速度不匹配矛盾.提高了系统的吞吐量. 缺点:系统资源利用率低(I/O请求成功前CPU空闲). 多道批

JavaSE知识-25(多线程(下))

25.01_多线程(单例设计模式) 单例设计模式:保证类在内存中只有一个对象. 如何保证类在内存中只有一个对象呢? (1)控制类的创建,不让其他类来创建本类的对象.private (2)在本类中定义一个本类的对象.Singleton s; (3)提供公共的访问方式. public static Singleton getInstance(){return s} 单例写法两种: (1)饿汉式 开发用这种方式 (2)懒汉式 面试写这种方式.多线程的问题? (3)第三种格式 饿汉式和懒汉式的区别 1,

DTD复习笔记(复习资料为菜鸟教程里的DTD教程)

DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块. DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用. 为什么使用 DTD? 通过 DTD,您的每一个 XML 文件均可携带一个有关其自身格式的描述. 通过 DTD,独立的团体可一致地使用某个标准的 DTD 来交换数据. 而您的应用程序也可使用某个标准的 DTD 来验证从外部接收到的数据. 您还可以使用 DTD 来验证您自身的数据 假如 DTD 被包含在您的 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYP