Java并发编程--1.Thread和Runnable
创建线程
Java有两种方式创建线程, 继承Thread类和实现Runnable接口
继承Thread
步骤:
1.自定义一个类继承Thread类, 重写run方法 2.创建自定义类的对象,调用start()
例如:
class MyThread extends Thread {
@Override
public void run() {
System.out.println("in thread");
}
}
MyThread thread = new MyThread();
thread.start();
实现Runnable
步骤:
1. 自定义一个类,实现Runnable,重写run() 2.创建一个Thread对象, 构造方法的参数是自定义类的对象, 调用start()
例如:
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("in Runable");
}
}
MyRunnable runnable = new MyRunnable();
new Thread(runnable).start();
Thread和Runnable的区别
买火车票的案例
买5张火车票,我们希望多个线程总共买5张票, 下面是两种实现的代码
继承Thread:
class MyThread extends Thread {
private int ticket = 5;
@Override
public void run() {
for (int i=0;i<10;i++) {
if(ticket > 0){
System.out.println("ticket = " + ticket--);
}
}
}
}
new MyThread().start();
new MyThread().start();
我们new了2个线程对象,分别独立的执行2个对象中的代码
控制台输出: 忽略输出顺序,可以看出2个线程分别卖了5张
ticket = 5
ticket = 4
ticket = 3
ticket = 5
ticket = 2
ticket = 4
ticket = 3
ticket = 2
ticket = 1
ticket = 1
实现Runnable接口:
class MyRunnable implements Runnable {
private int ticket = 5;
@Override
public void run() {
for (int i=0;i<10;i++) {
if(ticket > 0){
System.out.println("ticket = " + ticket--);
}
}
}
}
MyRunnable r = new MyRunnable();
new Thread(r).start();
new Thread(r).start();
两个Thread对象共享一个Runnable对象
控制台输出: 可以看出2个线程共买了5张, 达到了资源共享的目的
ticket = 5
ticket = 4
ticket = 3
ticket = 2
ticket = 1
Runnable的优势
通过上面的案例, 可以总结出:
1.数据能够被多个线程共享,实现了代码与数据是独立的
2.适合多个相同程序代码的线程区处理同一资源的情况
改变线程状态
线程中断: interrupt
线程的中断是一种协作机制,线程中断后并不一定立即中断,而是要求线程在合适的时间中断自己,每个线程都有一个boolean的中断标志,该属性不再Thread中
interrupt() : 只是设置线程的中断标志
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
//如果去掉这句, 下面的输出语句就会答应
return;
}
System.out.println("中断");
}
};
Thread t = new Thread(r);
t.start();
//主线程休眠,确保刚才启动的线程执行一段时间
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//中断线程
t.interrupt();
在主线程中启动新线程, 主线程休眠2秒钟, 新线程休眠5秒钟
2秒后主线程会中断新线程,新线程的休眠状态被打断, 抛出 InterruptedException
程序进入catch块中,执行return语句, 从run()返回,然后线程消亡
interrupted() : 线程中断返回true, 并清除线程状态
isInterrupted(): 线程中断返回true, 不能改变线程的状态
public static void main(String[] args) {
System.out.println(Thread.interrupted());
//中断
Thread.currentThread().interrupt();
System.out.println(Thread.interrupted());
System.out.println(Thread.interrupted());
}
//控制台输出: false true false
也就是说, interrupted()会改变中断状态
线程挂起 : Joining
join() : 在A线程中,调用B线程对象的该方法, 那么A线程等B线程执行完后再执行
public static int a = 0;
public static void main(String[] args) throws Exception {
Runnable r = new Runnable(){
@Override
public void run() {
for (int k = 0; k < 5; k++) {
a = a + 1;
}
System.out.println("a" + a);
}
};
Thread t = new Thread(r);
t.start();
t.join();
for (int i=0; i<1; i++) {
System.out.println("i=" + i);
}
}
控制台输出: a=5 i=0;
如果把 t.join()该行去掉, 则输出 i=0 a=5 ; 因为主线程首先获得时间片执行, 然后在执行其它线程
线程间通信: wait-notify 实现生产者 - 消费者模型
通过Object类的wait(), notify(), notifyAll()可以实现线程间的通信
wait() : 将当前线程置入休眠状态,直到接到通知或被中断为止
notify() : 如果有多个线程等待,则线程规划器任意挑选出其中一个wait()状态的线程来发出通知
nofityAll() : 使所有原来在该对象上wait的线程统统退出wait的状态
生产者和消费者在同一时间段共享同一存储空间, 生产者向空间内生产数据,消费者取出数据
下面是个例子:
public class ProductConsumer{
public static void main(String[] args) {
Shared s = new Shared();
new Producer(s).start();
new Consumer(s).start();
}
}
/** 负责存储数据 */
class Shared {
private char c;
private volatile boolean writeable = true;
synchronized void setSharedChar(char c) {
while (!writeable)
try {
wait();
}
catch (InterruptedException ie){
}
this.c = c;
System.out.println(c + " produced by producer.");
writeable = false;
notify();
}
synchronized char getSharedChar(){
while (writeable)
try{
wait();
}
catch (InterruptedException ie){
}
writeable = true;
notify();
System.out.println(c + " consumed by consumer.");
return c;
}
}
/** 生产者 */
class Producer extends Thread{
private final Shared s;
Producer(Shared s){
this.s = s;
}
@Override
public void run() {
for (char ch = 'A'; ch <= 'Z'; ch++){
synchronized (s) {
s.setSharedChar(ch);
}
}
}
}
/** 消费者 */
class Consumer extends Thread {
private final Shared s;
Consumer(Shared s) {
this.s = s;
}
@Override
public void run() {
char ch;
do {
synchronized (s) {
ch = s.getSharedChar();
}
}
while (ch != 'Z');
}
}
控制台输出:
A produced by producer.
A consumed by consumer. ...................
线程状态总结
现在我们能创建线程, 并能改变线程的状态,下图是对线程状态的总结

Java并发编程--1.Thread和Runnable的更多相关文章
- Java并发编程:Thread类的使用
Java并发编程:Thread类的使用 在前面2篇文章分别讲到了线程和进程的由来.以及如何在Java中怎么创建线程和进程.今天我们来学习一下Thread类,在学习Thread类之前,先介绍与线程相关知 ...
- 【转】Java并发编程:Thread类的使用
一.线程的状态 在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于对Thread类中的方法的理解. 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程包括以 ...
- 3、Java并发编程:Thread类的使用
Java并发编程:Thread类的使用 在前面2篇文章分别讲到了线程和进程的由来.以及如何在Java中怎么创建线程和进程.今天我们来学习一下Thread类,在学习Thread类之前,先介绍与线程相关知 ...
- 【Java并发编程】之六:Runnable和Thread实现多线程的区别(含代码)
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17161237 Java中实现多线程有两种方法:继承Thread类.实现Runnable接口 ...
- 【Java并发编程】之六:Runnable和Thread实现多线程的区别
Java中实现多线程有两种方法:继承Thread类.实现Runnable接口,在程序开发中只要是多线程,肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下 ...
- java并发编程(六)Runnable和Thread实现多线程的区别
http://blog.csdn.net/ns_code/article/details/17161237
- Java并发编程:Thread类的使用介绍
在学习Thread类之前,先介绍与线程相关知识:线程的几种状态.上下文切换,然后接着介绍Thread类中的方法的具体使用. 以下是本文的目录大纲: 一.线程的状态 二.上下文切换 三.Thread类中 ...
- Java并发编程:Thread类的使用(转载)
一:线程的状态: 在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread类中的方法的理解. 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程 ...
- java并发编程目录
java并发编程目录 Java多线程基础:进程和线程之由来 JAVA多线程实现的四种方式 Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition Jav ...
随机推荐
- Java Swing实战(二)下拉菜单组件JComboBox及其事件监听
接下来给"数据源配置"面板添加下拉框. /** * @author: lishuai * @date: 2018/11/26 13:51 */ public class Weimi ...
- Java的Collection.sort()方法
Java中的Collection.sort()方法能使用泛型对对象的变量进行排序,下面是两种方法. 文件名:student.java import java.util.*; import com.su ...
- win10 安装oracle 11gR2_database(内附下载地址)
前言:想要为了后续开展项目做准备,而且打算使用oracle,所以必须先安装oracle.本机 win 10 64位系统. 第一步,下载 oracle 下载地址,官网(需要登录注册): http://d ...
- 使用JSON实现分页
使用JSON实现分页可直接用 Fenye.html <!DOCTYPE html> <html> <head> <title>JSON分页</ti ...
- 第二十六天- C/S架构 通信流程 socket
1.C/S架构 C/S架构:Client与Server ,中文意思:客户端与服务器端架构,这种架构也是从用户层面(也可是物理层面)来划分的.这里客户端一般指需先安装再执行的应用程序,对操作系统依赖性较 ...
- 代码实现自定义TableView
实现效果(通过代码的方式实现TableCell 的创建) 实现过程: 实现过程两个部分 1 数据源的准备 本例子采用NSDictionary +NSArray 为数据源 (接口部分) (数据初始化部分 ...
- ArcGis实现画矩形(RectangleFeedBack)
private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e) ...
- javascript的继承实现
javascript虽然是一门面向对象的语言,但是它的继承机制从一开始设计的时候就不同于传统的其他面向对象语言,是基于原型的继承机制,但是在这种机制下,继承依然有一些不同的实现方式. 方法一:类式继承 ...
- 'webpack' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
npm updatea -g 很严重,把本地npm安装包都更新了,跟项目npm安装包版本不一,导致 意思是版本冲突,手动卸载了,重新安装还是最新版本,很是头疼.找同事的电脑拷贝了一份,然后复制过来报“ ...
- Linux wget安装详解
Wget是一个十分常用命令行下载工具,多数Linux发行版本都默认包含这个工具.如果没有安装可在 http://www.gnu.org/software/wget/wget.html下载最新版本,并使 ...