java 静态代码块 多线程,java多线程

为了解决“一边...一边...问题”,可以使用进程或者线程

进程与线程

什么是进程

进程是应用程序运行的单元

什么是线程

线程是进程的单元。在JVM中,线程是抢占式调度的,不是时间片轮转调度的。

进程与线程有什么区别

进程有独立的内存空间。线程堆内存共享,栈内存独立。

线程资源消耗比进程小。

因为一个进程中的多个线程是并发运行的。

Java程序的进程里至少包含主线程和垃圾回收线程(后台线程)。

并行与并发

并发:微观异步运行,宏观同步运行。可说在 同一“时间段”,不一定同一“时刻”进行。

在单cpu中,在一个时刻只有一个任务在进行,因为其采用时间片轮转调度,每个时间片对于cpu的运行速度而言非常短,所以在宏观上,给人的感觉还是很多个线程任务在同时进行

并行:真真切切的同一个时刻进行的事件。

创建进程

创建一个进程,运行命令“dxdiag”

方式一,使用Runtime

...

Runtime runtime=Runtime.getRuntime();

try{

runtime.exec("dxdiag");

}catch(IOException e){

System.out.println(e.getMessage());

}

...

方式二,使用ProcessBuilder

...

ProcessBuilder process=ProcessBuilder("dxdiag");

//ProcessBuilder process=ProcessBuilder("dxdiag");

//process.command("dxdiag");

try{

process.start();

}catch(IOException e){

System.out.println(e.getMessage());

}

...

创建线程

创建线程主要有两种方式:

1. 继承Thread类

Thread类及其子类称之为 线程类

public class ExtendsThreadDemo {

public static void main(String[] args) {

SingThread sing=new SingThread();

sing.start();

}

}

class SingThread extends Thread {

public void run() {

for (int i = 0; i < 50; i++) {

System.out.println("01_Singing"+i);

if(i==10)

{

PlayThread play=new PlayThread();

play.start();

}

}

}

}

class PlayThread extends Thread {

public void run() {

for (int i = 0; i < 50; i++) {

System.out.println("02_playing"+i);

}

}

}

2. 实现Runnable接口

public class ImplementsRunnable {

public static void main(String[] args) throws InterruptedException {

Singable singable=new Singable();

Thread sing=new Thread(singable,"唱歌");

for (int i = 0; i < 50; i++) {

System.out.println("02_playing"+i);

if(i==10){

sing.start();

Thread.sleep(100);

}

}

}

}

class Singable implements Runnable{

public void run() {

for (int i = 0; i < 50; i++) {

System.out.println("01_Singing"+i);

}

}

}

3. 两种方式使用匿名内部类创建线程

public static void main(String[] args) {

System.out.println("匿名内部类创建线程!");

new Thread(){

public void run(){

for (int i = 0; i < 50; i++) {

System.out.println("01_Singing"+i);

}

}

}.start();

new Thread(new Runnable() {

@Override

public void run() {

for (int i = 0; i < 50; i++) {

System.out.println("02_playing"+i);

}

}

}, "Play").start();

}

两种创建方式的比较

实现 三个

math?formula=%5Ccolor%7Bgreen%7D%7B%E7%8C%AA%E5%85%AB%E6%88%92%7D

math?formula=%5Ccolor%7Bgreen%7D%7B50%7D 个 西瓜!

继承Thread方式

public class ExtendsDemo {

public static void main(String[] args) {

new Eat("八戒A").start();

new Eat("八戒B").start();

new Eat("八戒C").start();

}

}

class Eat extends Thread {

private int num = 50;

public Eat(String name) {

super(name);

}

@Override

public void run() {

while (num > 0) {

System.out.println(this.getName() + "吃掉了" + num + "号西瓜!");

int i = num--;

/* try {

sleep(100);

} catch (InterruptedException e) {

throw new RuntimeException("线程休眠失败!",e);

}*/

}

}

}

结果:

八戒B吃掉了50号西瓜!

八戒A吃掉了50号西瓜!

八戒C吃掉了50号西瓜!

...

实现Runnable接口方式

public class ImplementsDemo {

public static void main(String[] args) {

Eatable eatable=new Eatable();

Thread eat_A=new Thread(eatable,"八戒A");

Thread eat_B=new Thread(eatable,"八戒B");

Thread eat_C=new Thread(eatable,"八戒C");

eat_A.start();

eat_B.start();

eat_C.start();

}

}

class Eatable implements Runnable {

private int num = 50;

@Override

public void run() {

while (num > 0) {

System.out.println(Thread.currentThread().getName() + "吃掉了" + num + "号西瓜!");

num--;

}

}

}

结果:

八戒A吃掉了50号西瓜!

八戒A吃掉了49号西瓜!

八戒A吃掉了48号西瓜!

...

继承方式 创建每一线程就创建一个各自的num,三个八戒吃了总数150个西瓜。

实现方式 创建一个对象去构造多个线程,每个线程都共享一个num,真正实现了三个八戒吃了50 个西瓜。

区别:

资源共享;资源不共享

代码设计更优美

操作复杂;操作简单

也许你会想到 关键字 static

public class ExtendsDemo {

public static void main(String[] args) {

new Eat("八戒A").start();

new Eat("八戒B").start();

new Eat("八戒C").start();

}

}

class Eat extends Thread {

private static int num = 50;

public Eat(String name) {

super(name);

}

@Override

public void run() {

while (num > 0) {

System.out.println(this.getName() + "吃掉了" + num + "号西瓜!");

int i = num--;

/* try {

sleep(100);

} catch (InterruptedException e) {

throw new RuntimeException("线程休眠失败!",e);

}*/

}

}

}

这样不就解决了 继承方式创建线程 资源不共享问题了吗?

static 真的好吗?

线程同步与线程安全

对于上述的代码分析:

在run()方法中,三个线程A、B、C

B

while (num > 0) {

A C到此处被网络等原因延迟

System.out.println(this.getName() + "吃掉了" + num + "号西瓜!");

int i = num--;

}

所以,三个线程可能同时打印吃西瓜,如果在num--前出现线程延迟,一旦延迟结束,则三个线程同时执行num--,可能有些西瓜就没有被吃掉,在最后还可能出现负数号码的西瓜。

为了解决上述的线程安全问题

同步代码块

同步方法

锁机制

1. 同步代码块

public class SynchronizedBlockDemo {

public static void main(String[] args) {

System.out.println("你好!这里是同步代码块解决线程安全问题!");

Runnable eatable = new Runnable() {

private int num = 50;

@Override

public void run() {

synchronized (this) {

while (num > 0) {

System.out.println(Thread.currentThread().getName() + "吃掉了" + num + "号西瓜");

try {

Thread.sleep(100);

} catch (InterruptedException e) {

throw new RuntimeException("线程休眠出错!", e);

}

num--;

}

}

}

};

Thread thread_A=new Thread(eatable,"八戒A");

Thread thread_B=new Thread(eatable,"八戒B");

Thread thread_C=new Thread(eatable,"八戒C");

thread_A.start();

thread_B.start();

thread_C.start();

}

}

2. 同步方法

public class SynchronizedMethodDemo {

public static void main(String[] args) {

System.out.println("你好!这里是同步方法解决线程安全问题!");

Eatable eatable=new Eatable();

Thread thread_A=new Thread(eatable,"八戒A");

Thread thread_B=new Thread(eatable,"八戒B");

Thread thread_C=new Thread(eatable,"八戒C");

thread_A.start();

thread_B.start();

thread_C.start();

}

}

class Eatable implements Runnable{

private int num=50;

@Override

public synchronized void run() {

while(num>0){

System.out.println(Thread.currentThread().getName()+"吃掉了"+num+"号西瓜!");

try{

Thread.sleep(123);

}catch (InterruptedException e){

throw new RuntimeException("线程休眠失败!",e);

}

num --;

}

}

}

3. 锁机制

创建锁 :private final ReentrantLock lock=new ReentrantLock();

使用锁:

lock.lock();

try{

//运行的 资源操作 逻辑代码

}finally{

lock.unlock();

}

例子全部代码:

public class LockDemo {

public static void main(String[] args) {

System.out.println("你好!这里是锁的使用!");

Eatable1 eatable1 = new Eatable1();

Thread eat_A = new Thread(eatable1, "八戒A");

Thread eat_B = new Thread(eatable1, "八戒B");

Thread eat_C = new Thread(eatable1, "八戒C");

eat_A.start();

eat_B.start();

eat_C.start();

}

}

class Eatable1 implements Runnable {

private int num = 50;

private final ReentrantLock lock=new ReentrantLock();

@Override

public void run() {

lock.lock();

try{

while (num > 0) {

System.out.println(Thread.currentThread().getName() + "吃掉了" + num + "号西瓜!");

try {

Thread.sleep(100);

} catch (Exception e) {

System.out.println(e.getMessage());

}

num--;

}

}finally {

lock.unlock();

}

}

}

为了性能

尽量减小synchronized和lock的作用域.

双重检查机制

while(num>0){

synchronized(this){

if(num>0){

System.out.println(Thread.currentThread().getName()+"吃掉了"+num+"号西瓜!");

try{

Thread.sleep(123);

}catch (InterruptedException e){

throw new RuntimeException("线程休眠失败!",e);

}

num --;

}

}

}

“双重检查加锁”机制的实现会使用关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。

注意:在java1.4及以前版本中,很多JVM对于volatile关键字的实现的问题,会导致“双重检查加锁”的失败,因此“双重检查加锁”机制只能用在java5及以上的版本。

由于volatile关键字可能会屏蔽掉虚拟机中一些必要的代码优化,所以运行效率并不是很高。因此一般建议,没有特别的需要,不要使用。

StringBuffer与StringBuilder的区别.

ArrayList和Vector的区别.

HashMap和Hashtable的区别.

StringBuffer 、Vector、 Hashable线程安全

懒汉单例与饿汉单例

懒汉单例 线程不安全

public class SingleLazyDemo {

public static void main(String[] args) {

System.out.println("你好!这里是单例的懒汉模型");

}

}

class SingleLazy {

private static SingleLazy singlelazy = null;

private SingleLazy(){}

public static SingleLazy getInstance() {

if (singlelazy == null) {

//此处存在线程安全问题

singlelazy = new SingleLazy();

}

return singlelazy;

}

}

class SingleLazy_1 {

private static SingleLazy_1 singlelazy1 = null;

private SingleLazy_1(){}

public synchronized static SingleLazy_1 getInstance() {

if (singlelazy1 == null) {

singlelazy1 = new SingleLazy_1();

}

return singlelazy1;

}

}

饿汉单例 线程安全

public class SingleHungeryDemo {

public static void main(String[] args) {

System.out.println("你好!这里是单例的饥汉模型!");

}

}

class SingleHunger {

private static SingleHunger singlehunger = new SingleHunger();

private SingleHunger() {

}

public static SingleHunger getInstance() {

return singlehunger;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值