Java的多线程
Java使用Thread代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用就是执行一段程序流(完成一定的任务)。
Java使用线程执行体来代表这段程序流。
1. 继承Thread类创建线程类
package org.apache;
public class ThreadDemo1 extends Thread {
private int i;
/*
* 重写run方法,也就是线程执行体
* 当线程类继承Thread类时,直接使用this即可取得当前线程
* 直接调用getName()方法即可返回当前线程的名字
*/
public void run(){
for ( ; i<100;i++){
System.out.println(getName() + " " + i);
}
}
public static void main(String[] args)
{
for (int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()
+ " "+i);
if(i==20){
//创建并启动第一个线程
new ThreadDemo1().start();
//创建并启动第二个线程
new ThreadDemo1().start();
}
}
}
}
执行结果:

注意:实际上该程序有三个线程,main()方法是主线程,显示的创建了两个子线程。
Thread-0和Thread-1 i的值是不连续的,所以Thread-0和Thread-1不能共享Thread类的实例变量。
2. 实现Runnable接口创建线程类
package org.apache;
public class ThreadDemo2 implements Runnable {
private int i;
//当实现Runnable接口时必须用Thread.currentThread().getName()获取当前线程
public void run() {
for ( ; i<100;i++){
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
public static void main(String[] args) {
for (int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName() + " "+i);
if (i==20){
ThreadDemo2 td = new ThreadDemo2();
//通过new Thread(target,name)方法创建线程
new Thread(td,"线程1").start();
new Thread(td,"线程2").start();
}
}
}
}
结果:

i的值是连续的,共享同一个线程类的实例变量(其实是线程的target类)
3.使用Callable和Future创建线程
FutureTask同时实现
Future接口--->接收call()方法的返回值
和Runnable接口--->可以作为Thread的target
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask; /*
* 创建并启动有返回值的线程步骤:
* 1. 创建Callable接口的实现类,并实现call()方法,作为线程执行体
* 2. 使用FutureTask类包装Callable对象,该FutureTask对象封装了Callable对象的call()方法
* 3. 使用FutureTask对象作为Thread对象的target创建并启动新线程
* 4. 调用FutureTask对象的get()方法获得子线程的执行结束的返回值
*/
public class ThreadDemo3 implements Callable{
private int i; public Object call() throws Exception {
for ( ; i<100;i++){
System.out.println(Thread.currentThread().getName() + " " + i);
}
return i;
} public static void main(String[] args) {
ThreadDemo3 td = new ThreadDemo3();
//通过new Thread(target,name)方法创建线程
FutureTask<Integer> task = new FutureTask<Integer>(td);
for (int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName() + " "+i);
if (i==20){
new Thread(task,"有返回值的线程").start();
}
}
try {
//获取线程返回值
System.out.println(task.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
结果:

4. 控制线程
4.1 join线程
当程序程序执行流中调用其它线程的join()方法时,调用线程将会被阻塞。直到被join的线程执行完成。
package org.apache;
public class ThreadDemo1 extends Thread {
public ThreadDemo1 (String name){
super(name);
}
private int i;
/*
* 重写run方法,也就是线程执行体
* 当线程类继承Thread类时,直接使用this即可取得当前线程
* 直接调用getName()方法即可返回当前线程的名字
*/
public void run(){
for ( ; i<100;i++){
System.out.println(getName() + " " + i);
}
}
public static void main(String[] args) throws InterruptedException
{
new ThreadDemo1("新线程").start();
for (int i=0;i<100;i++){
Thread task = new ThreadDemo1("被join的线程");
System.out.println(Thread.currentThread().getName()
+ " "+i);
if(i==20){
//创建并启动第一个线程
task.start();
//main调用了join()方法,必须等task执行结束后才会向下执行
task.join();
}
}
}
}
执行结果:

分析可知main方法(主线程)被阻塞,只有新线程和join线程并发执行。
4.2 守护线程
有一种线程是为其它线程提供服务的(典型的有GC),被称为后台线程或者守护线程。
package org.apache;
public class ThreadDemo4 extends Thread{
private int i;
public void run(){
for (;i<1000;i++){
System.out.println(getName() + " "+i);
}
}
public static void main(String[] args) {
ThreadDemo4 task = new ThreadDemo4();
//设置为守护进程
task.setDaemon(true);
task.start();
for( int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
//程序执行到此处就main进程就结束了,JVM将会主动退出,守护线程也将被结束,无法执行到=999
}
}
执行结果:

4.3 线程睡眠:sleep
package org.apache;
import java.util.Date;
public class ThreadDemo5 {
//正在执行的线程将会暂停一段时间,进入阻塞状态
public static void main(String[] args) throws InterruptedException {
for (int i=0;i<10;i++){
System.out.println("当前时间: "+new Date());
Thread.sleep(1000);
}
}
}
结果:

Java的多线程的更多相关文章
- Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- java之多线程 二
线程的生命周期: 当线程被创建并被启动时,它既不是一启动就进入了执行状态,在线程的生命周期中,它要经过new(新建),就绪(Runnable),运行(Running),阻塞(Blocked),dead ...
- Java的多线程机制系列:(一)总述及基础概念
前言 这一系列多线程的文章,一方面是个人对Java现有的多线程机制的学习和记录,另一方面是希望能给不熟悉Java多线程机制.或有一定基础但理解还不够深的读者一个比较全面的介绍,旨在使读者对Java的多 ...
- Java Thread 多线程 介绍
1.线程概述 几乎所有的操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序就是一个进程. 当一个程序运行时,内部可能包含了多个顺序执行流,每个顺序执行流就是一个线程. 2.线程 ...
- Java:多线程<一>
程序运行时,其实是CPU在执行程序的进程,为了提高工作效率一个进程可以有多个线程. Java的多线程: 其实我们之前就见过Java的线程,main就是Java的一个线程,还有另一个条线程总是和main ...
- Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- Java的多线程机制系列:(三)synchronized的同步原理
synchronized关键字是JDK5之实现锁(包括互斥性和可见性)的唯一途径(volatile关键字能保证可见性,但不能保证互斥性,详细参见后文关于vloatile的详述章节),其在字节码上编译为 ...
- Java基础——多线程
Java中多线程的应用是非常多的,我们在Java中又该如何去创建线程呢? http://www.jianshu.com/p/40d4c7aebd66 一.常用的有三种方法来创建多线程 新建一个类继承自 ...
- JAVA之多线程的创建
转载请注明源出处:http://www.cnblogs.com/lighten/p/5967853.html 1.概念 老调重弹,学习线程的时候总会牵扯到进程的概念,会对二者做一个区分.网上有较多的解 ...
- Java基础--多线程的方方面面
1,什么是线程?线程和进程的区别是什么? 2,什么是多线程?为什么设计多线程? 3,Java种多线程的实现方式是什么?有什么区别? 4,线程的状态控制有哪些方法? 5,线程安全.死锁和生产者--消费者 ...
随机推荐
- [技术选型] CDH-Cloudera Distribution Hadoop
hadoop是一个开源项目,所以很多公司在这个基础进行商业化,Cloudera对hadoop做了相应的改变. Cloudera公司的发行版,我们将该版本称为CDH(Cloudera Distribut ...
- Patterns for Asynchronous MVVM Applications: Commands
Stephen Cleary Download the Code Sample This is the second article in a series on combining async an ...
- Selenium常用操作汇总二——如何操作cookies(转)
Web 测试中我们经常会接触到Cookies,一个Cookies主要属性有”所在域.name.value.有效日期和路径",下面来讲一下怎么操作Cookies. import java.ut ...
- php 文件上传类,功能相当齐全,留作开发中备用吧。
收藏一个经典好用的php 文件上传类,功能相当齐全,留作开发中备用吧. 好东西,大家都喜欢,才是真的好,哈哈!!! <?php /** * 文件上传类 */ class upload ...
- Linux及Windows系统配置JDK环境变量
1.Linux系统配置方法 记住,要下载JDK-8u121-linux-x64.tar.gz,而不是JRE-8u121-linux-x64.tar.gz,JDK中含很多开发者实用工具,比如javac. ...
- [深入理解Android卷一全文-第三章]深入理解init
因为<深入理解Android 卷一>和<深入理解Android卷二>不再出版,而知识的传播不应该因为纸质媒介的问题而中断,所以我将在CSDN博客中全文转发这两本书的全部内容. ...
- js 形如 "1,2,3"的操作
查找指定元素在数组中的index. var arr=[1,2,3]; $.inArray(2, arr);//返回1 arr.splice($.inArray(2, arr),1); //从数组中删除 ...
- MySQL的varchar长度问题
From: http://blog.csdn.net/longyulu/article/details/7863737 http://dinglin.iteye.com/blog/914276 htt ...
- WiFidog 广告路由可修改功能更加智能化的几点看法
海蜘蛛Tomato出了mini版,这个对很多做WiFi营销的朋友来说,是一个福音,因为可以直接从FIR302B,一台30多块钱的路由直接刷成Hi-WiFi,而且界面这么漂亮 相信很多人已经对此界面OE ...
- Centos7 安装redis服务
Redis的安装 1.先安装gcc编译器,否则make的时候会报错 yum -y install gcc 2.下载redis安装包,解压编译安装 $ wget http://download.redi ...