Java多线程操作

Java中的线程

一个程序的运行须要启动一个应用进程,一个进程能够创建多个线程。帮助应用完毕多任务操作。实现并发运行。在Java中线程是被封装成Thread类。进行多线程操作时仅仅须要继承一个Thread类,实现自己的功能就可以。然后开启此线程,或者你也能够实现一个Runnable接口。然后将其传递给Thread对象。然后再启动它。

线程的创建于启动

继承Thread

创建一个类并继承Thread类,然后实现Thread类的run方法,在run方法内填上自己的代码。然后创建这个自己定义类,并调用其start方法来启动这个自己定义线程。

// 引入Thread
import java.lang.Thread;

/**
 * 创建自己的Thread,实现run方法(放上自己要运行的内容)
 */
class MyThread extends Thread {

    /**
     * 覆盖超类Thread的run方法
     */
    public void run() {
        for(int i=0; i<10; i++) {
            System.out.println("第" + i + "次循环");
        }
    }
}
class ThreadDemo1 {
    public static void main(String[] args) {
        // 创建一个自己定义线程。而且启动它
        new MyThread().start();
    }
}
/* 程序输出:
第0次循环
第1次循环
第2次循环
第3次循环
第4次循环
第5次循环
第6次循环
第7次循环
第8次循环
第9次循环
*/

实现Runnable

一个实现过Runnable的对象都能够被一个Thread对象所运行。

import java.lang.Thread;
import java.lang.Runnable;
/**
 * 创建一个类,实现Runnable接口。

*/
class MyRunnable implements Runnable {

    /**
     * 实现Runnable的run方法
     */
    public void run() {
        for(int i=0; i<5; i++) {
            System.out.println("Runable:第" + i + "次循环");
        }
    }
}
class ThreadDemo2 {
    public static void main(String[] args) {
        // 创建一个线程。并创建一个实现过Runnable的对象
        // 构造它,然后再启动这个线程
        new Thread(new MyRunnable()).start();
    }
}
/* 程序输出:
Runable:第0次循环
Runable:第1次循环
Runable:第2次循环
Runable:第3次循环
Runable:第4次循环
*/

synchronized的使用

既然是多线程。那么就会出现多线程的问题。如同一时候訪问同一资源。从而产生意料之外的结果。这是我们所不想看到的。在Java中能够非常easy的解决问题。使用synchronized对操作进行加锁。synchronized能够对对象加锁,也能够对函数进行加锁。以下对照一下未使用synchronized和使用synchronized的不同之处。

未使用synchronized的情况

import java.lang.Thread;
import java.lang.Runnable;

class MyRunnable implements Runnable {
    private static int i=0;
    public void run() {
        for(; i<10; i++) {
            try {
                Thread.sleep(10);
            } catch(Exception e) {

            }
            print(i);
        }
    }

    private void print(int k) {
        System.out.println(k);
    }
}

class Demo {
    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();
        new Thread(r).start();
        new Thread(r).start();
    }
}

能够看到结果不对,由于两个线程可能会同一时候进入线程,然后打印出两个同样的值。

0
0
2
3
4
5
6
7
8
9
10

使用了synchronized后的情况

import java.lang.Thread;
import java.lang.Runnable;

class MyRunnable implements Runnable {
    private static int i=0;
    public void run() {
        synchronized(this) {
            for(; i<10; i++) {
                try {
                    Thread.sleep(10);
                } catch(Exception e) {

                }
                print(i);
            }
        }
    }

    private void print(int k) {
        System.out.println(k);
    }
}

class Demo {
    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();
        new Thread(r).start();
        new Thread(r).start();
    }
}

当对for进行加锁处理后,便不会同一时候两个线程进入循环,这样打印的数字便不会出错。

0
1
2
3
4
5
6
7
8
9

synchronized的加锁对象会有一个标志位(0/1)。默认的情况下是0,当线程运行到synchronized的加锁对象后假设对象的标志位为0。那么将其设置为1,否则等待。

这个标志位能够称之为“锁旗标”。这样以来便能够实现线程同步。

尽管synchronized攻克了多线程的不安全问题。可是也是有一定的弊端的。它会减少程序的运行效率,所以。synchronized不能够任意放置,应尽量将其放到必须使用的位置上。

如单例模式的一个样例:

public class Single {

    private Single mInstance;

    private Single(){

    }

    public static Single getInstance() {
        if(mInstance == null) {
            synchronized(Single.class) {
                if(mInstance == null) {
                    mInstance = new Single();
                }
            }
        }
        return mInstance;
    }
}

这里的synchronized能够加在getInstance()前面,可是这样会大大减少运行效率,也能够去掉外层的if(mInstance == null),可是这样也会添加不必要的推断,以为假设mInstance已经创建后便不须要锁了。若此以来,上面这样的写法是最好的。

最内层的if推断有必要说明一下,能够假设这样一种情况,两个线程都运行到第一个if的后面,那么。假设没有内层的if推断的话,mInstance会被创建两次,所以,内层的if是不可或缺的。

waitnotify的使用

waitnotify是Object对象中的两个方法。其作用是用于多线程中的控制,如想使用两个线程交替打印出OddEven时,详细代码例如以下:

import java.lang.Thread;
import java.lang.Runnable;

class Temp {
    public static boolean flag = false;
}

class Odd implements Runnable{

    public void run() {
        while(true) {
            if(Temp.flag) {
                try {
                    wait();
                } catch(Exception e) {}
            }
            System.out.println("Odd");
            Temp.flag = !Temp.flag;
            try {
                notify();
            } catch(Exception e) {}
        }
    }
}

class Even implements Runnable {

    public void run() {
        while(true) {
            if(!Temp.flag) {
                try {
                    wait();
                } catch(Exception e) {}
            }
            System.out.println("Even");
            Temp.flag = !Temp.flag;
            try {
                notify();
            } catch(Exception e) {}
        }
    }
}

class Demo {
    public static void main(String[] args) {
        new Thread(new Odd()).start();
        new Thread(new Even()).start();
    }
}

当然除了notify方法,还有notifyAll方法。用于唤醒全部线程。

Lock的使用

JDK1.5之后。也就是Java5.0之后。添加了很多新的内容,如用于线程控制的一些类,Lock的用法相当于synchronizedLocklock()unlock()分别用于加锁和解锁,一般用法例如以下:

import java.lang.Runnable;
import java.lang.Thread;
import java.util.concurrent.locks.*;

class Locks implements Runnable {
    private Lock lock = new ReentrantLock();
    private int index = 0;
    public void run() {
        while(true) {
            lock.lock();
            System.out.print(index + " ");
            try {
                Thread.sleep(100);
            } catch(Exception e) {}
            index ++;
            lock.unlock();
        }
    }
}

class Demo {
    public static void main(String[] args) {
        Locks locks = new Locks();
        new Thread(locks).start();
        new Thread(locks).start();
        new Thread(locks).start();
    }
}

这样便能够顺序打印出0 1 2 3 4 ···

通过Lock的对象,我们能够创建Condition对象,如

Condition condition = lock.newCondition();

然后能够使用condition.await();condition.signal()来暂停和唤醒线程,当然还有condition.signalAll()来唤醒全部线程。

时间: 2024-10-24 21:39:34

Java多线程操作的相关文章

黑马程序员-Java多线程操作

--Java培训.Android培训.iOS培训..Net培训.期待与您交流!--- Java中的线程 一个程序的运行需要启动一个应用进程,一个进程可以创建多个线程,帮助应用完成多任务操作,实现并发运行.在Java中线程是被封装成Thread类,进行多线程操作时只需要继承一个Thread类,实现自己的功能即可,然后开启此线程,或者你也可以实现一个Runnable接口,然后将其传递给Thread对象,然后再启动它. 线程的创建于启动 继承Thread 创建一个类并继承Thread类,然后实现Thr

【转】Java多线程操作局部变量与全局变量

原文网址:http://blog.csdn.net/undoner/article/details/12849661 在这篇文章里,我们首先阐述什么是同步,不同步有什么问题,然后讨论可以采取哪些措施控制同步,接下来我们会仿照回顾网络通信时那样,构建一个服务器端的“线程池”,JDK为我们提供了一个很大的concurrent工具包,最后我们会对里面的内容进行探索. 为什么要线程同步? 说到线程同步,大部分情况下, 我们是在针对“单对象多线程”的情况进行讨论,一般会将其分成两部分,一部分是关于“共享变

用java多线程操作模拟售票系统

class Threadsale implements Runnable{ int tickets = 100; public void run(){ while(true){ if(tickets>0){ System.out.println(Thread.currentThread().getName()+"售车票第"+tickets--+"号"); } else System.exit(0); } } } public class DemoThread

java多线程学习之——多线程中几种释放锁和不释放锁的操作

在学习java多线程这一块知识的时候,遇到了很多个关于线程锁什么时候释放的问题,现总结几种释放锁和不释放锁的操作如下: 不释放锁: 线程执行同步代码块或同步方法时,程序调用Thread.sleep(Long l).Thread.yield()方法暂停当前线程的执行 线程执行同步代码块时,其它线程调用该线程suspend()方法将该线程挂起,该线程不会释放锁(同步监视器) 尽量避免使用suspend()和resume()来控制线程 释放锁: 当前线程的同步方法.同步代码块执行结束 当前线程的同步方

Java多线程对同一个对象进行操作

示例: 三个窗口同时出售20张票. 程序分析: 1.票数要使用一个静态的值. 2.为保证不会出现卖出同一张票,要使用同步锁. 3.设计思路:创建一个站台类Station,继承THread,重写run方法,在run方法内部执行售票操作! 售票要使用同步锁:即有一个站台卖这张票时,其他站台要等待这张票卖完才能继续卖票! package com.multi_thread; //站台类 public class Station extends Thread { // 通过构造方法给线程名字赋值 publ

从JAVA多线程理解到集群分布式和网络设计的浅析

对于JAVA多线程的应用非常广泛,现在的系统没有多线程几乎什么也做不了,很多时候我们在何种场合如何应用多线程成为一种首先需要选择的问题,另外关于java多线程的知识也是非常的多,本文中先介绍和说明一些常用的,在后续文章中如果有必要再说明更加复杂的吧,本文主要说明多线程的一下几个内容: 1.在应用开发中什么时候选择多线程? 2.多线程应该注意些什么? 3.状态转换控制,如何解决死锁? 4.如何设计一个具有可扩展性的多线程处理器? 5.多线程联想:在多主机下的扩展-集群? 6.WEB应用的多线程以及

Rhythmk 一步一步学 JAVA (21) JAVA 多线程

1.JAVA多线程简单示例 1.1 .Thread  集成接口 Runnable 1.2 .线程状态,可以通过  Thread.getState()获取线程状态: New (新创建) Runnable (可以运行) Blocked  (被阻塞) Waiting  (等待) Timed waiting (计时等待) Terminated  (被终止) ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

(转载)Java多线程入门理解

转载出处http://blog.csdn.net/evankaka 写在前面的话:此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢?如果你觉得此文很简单,那推荐你看看Java并发包的的线程池(Java并发编程与技术内幕:线程池深入理解),或者看这个专栏:Java并发编程与技术内幕.你将会对Java里头的高并发场景下的线程有更加深刻的理解. 目录(?)[-] 一扩展javalangThread类 二实现javalan

Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock

ReentrantLock介绍 ReentrantLock是一个可重入的互斥锁,又被称为"独占锁". 顾名思义,ReentrantLock锁在同一个时间点只能被一个线程锁持有:而可重入的意思是,ReentrantLock锁,可以被单个线程多次获取.ReentrantLock分为"公平锁"和"非公平锁".它们的区别体现在获取锁的机制上是否公平."锁"是为了保护竞争资源,防止多个线程同时操作线程而出错,ReentrantLock在