您现在的位置是:主页 > news > 用香港阿里云做网站好有钱/日本樱花免m38vcom费vps

用香港阿里云做网站好有钱/日本樱花免m38vcom费vps

admin2025/4/25 14:28:59news

简介用香港阿里云做网站好有钱,日本樱花免m38vcom费vps,电脑传奇网站,如何在阿里巴巴做网站2019独角兽企业重金招聘Python工程师标准>>> 1. volatile与Java内存模型(JMM) 有关volatile的解释,最常见的说法是“易变的,不稳定的”。 当你用volatile去声明一个变量时,就等于告诉了虚拟机,这…

用香港阿里云做网站好有钱,日本樱花免m38vcom费vps,电脑传奇网站,如何在阿里巴巴做网站2019独角兽企业重金招聘Python工程师标准>>> 1. volatile与Java内存模型(JMM) 有关volatile的解释,最常见的说法是“易变的,不稳定的”。 当你用volatile去声明一个变量时,就等于告诉了虚拟机,这…

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

1. volatile与Java内存模型(JMM)

    有关volatile的解释,最常见的说法是“易变的,不稳定的”。

    当你用volatile去声明一个变量时,就等于告诉了虚拟机,这个变量极有可能被某些程序或线程修改。为了确保这个变量被修改后,应用程序范围内的所有线程都能“看到”改动,虚拟机就必须用一种特殊的手段,保证这个变量的可见性等特点。

    volatile能保证数据的有效性和可见性,看一个例子:

package cn.net.bysoft.java.concurrency.design.ch02;public class Example10 extends Thread {private static boolean ready;private static int number;@Overridepublic void run() {while(!ready);System.out.println(number);}public static void main(String[] args) throws InterruptedException {new Example10().start();Thread.sleep(1000);number = 42;ready = true;Thread.sleep(10000);}}

    在虚拟机Client模式下,由于JIT并没有做足够的优化,主线程修改ready变量的状态后,次线程可以发现这个改动并退出程序。但是在Server模式下,由于系统优化的结果,次线程无法看到主线程的修改,导致程序永远无法退出。

    这里只要用volatile修饰ready变量就可以解决这个问题了。

2. 线程组

    在一个系统中,如果线程数量很多,而且功能分配比较明确,就可以将相同功能的线程放置在一个线程组里。线程组的使用非常简单,例如:

package cn.net.bysoft.java.concurrency.design.ch02;public class Example11 implements Runnable {public static void main(String[] args) {ThreadGroup tg = new ThreadGroup("PrintGroup");Thread t1 = new Thread(tg, new Example11(), "T1");Thread t2 = new Thread(tg, new Example11(), "T2");t1.start();t2.start();System.out.println(tg.activeCount());tg.list();}@Overridepublic void run() {String groupAndName = Thread.currentThread().getThreadGroup().getName() + "-"+ Thread.currentThread().getName();while(true) {System.out.println("I am " + groupAndName);try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

    上面代码输出:

2
I am PrintGroup-T1
I am PrintGroup-T2
java.lang.ThreadGroup[name=PrintGroup,maxpri=10]Thread[T1,5,PrintGroup]Thread[T2,5,PrintGroup]
I am PrintGroup-T2
I am PrintGroup-T1
I am PrintGroup-T1
I am PrintGroup-T2
...
...

    强烈建议大家在创建线程和线程组的时候,给他们取一个好听的名字,在出现问题时就不会拿到一连串的Thread-0、Thread-1和Thread-2这样的名称了。

3. 守护线程

    守护线程是一种特殊的线程,在后台默默地完成一些系统性的服务,比如垃圾回收线程、JIT线程就可以理解为守护线程。与之对应的是用户线程,用户线程可以认为是系统的工作线程,如果用户线程全部结束,守护线程就没有要守护的对象了,应用程序自然就结束了,看一个例子:

package cn.net.bysoft.java.concurrency.design.ch02;public class Example12 {public static class DaemonT extends Thread {@Overridepublic void run() {while(true) {System.out.println("I am alive");try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}public static void main(String[] args) throws InterruptedException {Thread t = new DaemonT();t.setDaemon(true);t.start();Thread.sleep(2000);}}

    在这个例子中,由于t是守护线程,系统中只有main是用户线程,因此在mian休眠2秒退出时,整个程序也结束了。

    注意,setDaemon()方法要在start()前设置,在之后设置虽然也可以运行,但只会作为用户线程看待。

4. 线程优先级

    在Java中,使用1到10表示线程优先级。一般可以使用内置的三个静态标量表示:

public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;

    数字越大,优先级越高,例如:

package cn.net.bysoft.java.concurrency.design.ch02;public class Example13 {public static class HightPriority extends Thread {static int count = 0;@Overridepublic void run() {while (true) {synchronized (Example13.class) {count++;if (count > 10000000) {System.out.println("HightPriority is complete");break;}}}}}public static class LowPriority extends Thread {static int count = 0;@Overridepublic void run() {while (true) {synchronized (Example13.class) {count++;if (count > 10000000) {System.out.println("LowPriority is complete");break;}}}}}public static void main(String[] args) {Thread high = new HightPriority();Thread low = new LowPriority();high.setPriority(Thread.MAX_PRIORITY);low.setPriority(Thread.MIN_PRIORITY);low.start();high.start();}}

    在大部分情况下,高优先级会比低优先级先完成,但不能确保所有情况下都会这样。

5.线程安全的概念与synchronized

    关键字synchronized的作用是实现线程间的同步。它的工作是对同步的代码加锁,使得每一次只有一个线程能进入同步的代码块。

    synchronized可以有多种用法,简单整理:

  • 指定加锁对象:对给定对象加锁,进入同步代码前要获得给定的对象锁;
  • 直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁;
  • 直接作用于静态方法:相当与对当前类加锁,进入同步代码前要获得当前类的锁;

    看一个简单的例子,描述给对象加锁:

package cn.net.bysoft.java.concurrency.design.ch02;public class Example14 implements Runnable {static Example14 instance = new Example14();static int i = 0;public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(new Example14());Thread t2 = new Thread(new Example14());t1.start();t2.start();t1.join();t2.join();System.out.println(i);}@Overridepublic void run() {for(int j = 0 ;j< 10000000;j++) {synchronized(instance) {i++;}}}}

    上诉代码也可以写成一下形式:

package cn.net.bysoft.java.concurrency.design.ch02;public class Example14 implements Runnable {static Example14 instance = new Example14();static int i = 0;public synchronized void increase() {i++;}public static void main(String[] args) throws InterruptedException {// Thread t1 = new Thread(new Example14());// Thread t2 = new Thread(new Example14());Thread t1 = new Thread(instance);Thread t2 = new Thread(instance);t1.start();t2.start();t1.join();t2.join();System.out.println(i);}@Overridepublic void run() {for (int j = 0; j < 10000000; j++) {// synchronized(instance) {// i++;// }increase();}}}

    上面代码将第一个t1和t2的声明注释了,如果不想注释,则可以写成:

package cn.net.bysoft.java.concurrency.design.ch02;public class Example14 implements Runnable {static Example14 instance = new Example14();static int i = 0;public static synchronized void increase() {i++;}public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(new Example14());Thread t2 = new Thread(new Example14());t1.start();t2.start();t1.join();t2.join();System.out.println(i);}@Overridepublic void run() {for (int j = 0; j < 10000000; j++) {// synchronized(instance) {// i++;// }increase();}}}

    将increase()方法用static修饰后,锁就会加到对象上,而不是实例上。

转载于:https://my.oschina.net/u/2450666/blog/831015