创建线程

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的更多相关文章

  1. Java并发编程:Thread类的使用

    Java并发编程:Thread类的使用 在前面2篇文章分别讲到了线程和进程的由来.以及如何在Java中怎么创建线程和进程.今天我们来学习一下Thread类,在学习Thread类之前,先介绍与线程相关知 ...

  2. 【转】Java并发编程:Thread类的使用

    一.线程的状态 在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于对Thread类中的方法的理解. 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程包括以 ...

  3. 3、Java并发编程:Thread类的使用

    Java并发编程:Thread类的使用 在前面2篇文章分别讲到了线程和进程的由来.以及如何在Java中怎么创建线程和进程.今天我们来学习一下Thread类,在学习Thread类之前,先介绍与线程相关知 ...

  4. 【Java并发编程】之六:Runnable和Thread实现多线程的区别(含代码)

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17161237 Java中实现多线程有两种方法:继承Thread类.实现Runnable接口 ...

  5. 【Java并发编程】之六:Runnable和Thread实现多线程的区别

    Java中实现多线程有两种方法:继承Thread类.实现Runnable接口,在程序开发中只要是多线程,肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下 ...

  6. java并发编程(六)Runnable和Thread实现多线程的区别

    http://blog.csdn.net/ns_code/article/details/17161237

  7. Java并发编程:Thread类的使用介绍

    在学习Thread类之前,先介绍与线程相关知识:线程的几种状态.上下文切换,然后接着介绍Thread类中的方法的具体使用. 以下是本文的目录大纲: 一.线程的状态 二.上下文切换 三.Thread类中 ...

  8. Java并发编程:Thread类的使用(转载)

    一:线程的状态: 在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread类中的方法的理解. 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程 ...

  9. java并发编程目录

    java并发编程目录 Java多线程基础:进程和线程之由来 JAVA多线程实现的四种方式 Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition Jav ...

随机推荐

  1. QQ简易版

    package QQ; /* * * 登录界面 * */ import javax.swing.*; import java.awt.event.ActionEvent; import java.aw ...

  2. Hive 基础你需要掌握这些

    HDFS 中一个简单的 Join查询,是否需要撸一大串代码?我只会SQL语句 能不能入坑大数据?这里我们就来聊一聊 Hive. Hive 是什么? Hive 是一种数据仓库工具,不提供数据存储(数据还 ...

  3. MQ之如何做到消息幂等 (转 优秀)

    一.缘起 MQ消息必达,架构上有两个核心设计点: (1)消息落地 (2)消息超时.重传.确认 再次回顾消息总线核心架构,它由 发送端.服务端.固化存储.接收端 四大部分组成. 为保证消息的可达性,超时 ...

  4. spring boot 入门一 构建spring boot 工程

    最近在学习Spring boot,所以想通过博客的形式和大家分享学习的过程,同时也为了更好的学习技术,下面直接进入Spring boot的世界. 简介 spring boot 它的设计目的就是为例简化 ...

  5. mootools vs jquery

    大部分最近才剛接觸JavaScript的人會面臨到的困難是該選擇哪個套件(library)或是該先學哪個套件.如果你在一間公司裡上班,那麼可能公司已經有一套固定使用的套件,若是在這種情況下,問題就沒那 ...

  6. 使用office打印到文件功能进行打印测试

     大家在日常的支持工作中常会遇到各种打印问题,所以进行一些打印测试也在所难免.但是每次跑来跑去浪费了宝贵的时间,打印又浪费了纸张资源.我们也会想到安装虚拟打印机,但因为没有合适的软件,结果是我们只 ...

  7. 初次使用git就遭遇不测,提示没有这个服务连接和需要配置git的一个http参数 NO network connection,SSl host could not be verified ...

    第一次使用git 拉取服务上的项目到本地,结果,在拿到访问的url地址后,输入用户名密码,失败了. --eclispe  4.5.3 继承了git客户端插件的版本 ------下一步后,报错 NO n ...

  8. Centos 安装Dokuwiki

    一.前言 DokuWiki是一个开源wiki引擎程序,运行于PHP环境下.DokuWiki程序小巧而功能强大.灵活,适合中小团队和个人网站知识库的管理. 二.环境 在centos6 下安装apache ...

  9. 设计可以多选的按钮ChooseManyButton

    设计可以多选的按钮ChooseManyButton 效果: 源码: ChooseManyButton.h 与 ChooseManyButton.m // // ChooseManyButton.h / ...

  10. 使用NSClassFromString

    使用NSClassFromString 使用NSClassFromString可以直接从字符串初始化出对象出来,即使不引用头文件也没关系,以下是源码: AppDelegate.m // // AppD ...