jdk线程的简单使用
一、线程的实现方式
方式一:继承Thread类
一个类只要继承了Thread类,并重写run()方法,则就可以实现多线程的操作。
public class ThreadDemo01 { public static void main(String[] args) {
Thread1 thread1 = new Thread1("thread1");
Thread2 thread2 = new Thread2("thread2"); System.out.println(thread1.getName());
System.out.println(thread2.getName()); thread1.start();//启动线程
thread2.start();
}
} class Thread1 extends Thread {
public Thread1(String name) {
super(name);
} @Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Thread1 : " + i);
}
}
} class Thread2 extends Thread {
public Thread2(String name) {
super(name);
} @Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Thread2 : " + i);
}
}
}
方式二:实现Runnable接口
一个类只要实现了Runnable类,并重写run()方法,则就可以实现多线程的操作。
public class ThreadDemo03 { public static void main(String[] args) {
Thread thread1 = new Thread(new MyThread1(), "thread1");
Thread thread2 = new Thread(new MyThread2(), "thread2"); System.out.println(thread1.getName());
System.out.println(thread2.getName()); thread1.start();//启动线程
thread2.start();
}
} class MyThread1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("MyThread1 :" + i);
}
}
} class MyThread2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("MyThread2 :" + i);
}
}
}
两种启动方式的比较:
将我们希望线程执行的代码放到run方法中,然后通过start方法来启动线程,start方法首先为线程的执行准备好系统资源,然后再去调用run方法;
两种方法均需执行线程的start方法为线程分配必须的系统资源,调度线程运行并执行线程的run方法;在使用的时候使用实现接口优先(避免单继承);实现Runnable接口的方式能够实现资源的共享。
二、Thread的JDK源码分析
Thread thread1 = new Thread(new MyThread1(), "thread1");
Thread 构造方法源码如下:
public Thread(String name) {
init(null, null, name, 0);
} public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
} public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
} public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
…..
this.name = name.toCharArray();
this.target = target;
…..
}
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
public void run() {
if (target != null) {
target.run();
}
}
1)当生成一个线程对象时,如果没有为其设定名字,那么线程对象的名字将使用如下形式:Thread-number,该number将是自动增加的,并被所有的Thread对象所共享(因为它是static的成员变量);
2)当使用继承Thread类来生成线程对象时,我们需要重写run()方法,因为Thread类的run()方法此时什么事情都没做(target==null);
3)当使用实现Runnable接口来生成线程对象时,我们需要实现Runnable接口的run()方法,然后使用new Thread(new MyThread())(假使MyThread已经实现了Runnable接口)来生成线程对象,这时的线程对象的run()方法就会调用MyThread类的run方法,这样我们自己编写的run()方法就执行了。
三、线程中成员变量和局部变量的使用
1)如果一个变量是成员变量,那么多个线程对同一个对象的成员变量进行操作时,他们对该成员变量是彼此影响的(也就是说一个线程对成员变量的改变会影响到另一个线程)。
public class ThreadDemo04 {
public static void main(String[] args) {
HelloThread r = new HelloThread();
Thread thread1 = new Thread(r);
Thread thread2 = new Thread(r); thread1.start();
thread2.start();
}
} class HelloThread implements Runnable {
int i; //成员变量 @Override
public void run() {
while (true) {
System.out.println("number: " + this.i++); try {
Thread.sleep((long) (Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
} if (10 == this.i) {
break;
}
}
}
}
结果是:
number: 0
number: 1
number: 2
number: 3
number: 4
number: 5
number: 6
number: 7
number: 8
number: 9
2)如果一个变量是局部变量,那么每个线程都会有一个该局部变量的拷贝,一个线程对该局部变量的改变不会影响到其他的线程。
public class ThreadDemo05 {
public static void main(String[] args) {
WorldThread r = new WorldThread();
Thread thread1 = new Thread(r);
Thread thread2 = new Thread(r); thread1.start();
thread2.start();
}
} class WorldThread implements Runnable { @Override
public void run() {
int i = 0;
while (true) {
System.out.println("number: " + i++); try {
Thread.sleep((long) (Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
if (10 == i) {
break;
}
}
}
}
结果是:
number: 0
number: 0
number: 1
number: 1
……
四、卖票示例
50张票,3个窗口买,每个窗口相当于一个线程。
使用继承Thread类的方式卖票:
class MyThread1 extends Thread {
private Integer num = 50;
public MyThread1(String name) {
super(name);
}
public void run() {
int count = 0;
for (int i = 1; i <= 200; i++) {
if(num > 0){
count ++;
System.out.println(getName() + "卖出第--->" + num-- +"张票");
}
}
System.err.println(getName()+"卖了"+ count +"张票" );
}
}
getName()方法来自于Thread类中,故可以直接获得。
使用实现Runnable的方式卖票:
class MyThread2 implements Runnable{
private Integer num = 50;
public void run() {
int count = 0;
for (int i = 0; i < 200 ; i++) {
if(num > 0){
count ++;
System.out.println(Thread.currentThread().getName()
+ "卖出第--->" + num-- +"张票");
}
}
System.err.println(Thread.currentThread().getName()
+ "卖了"+ count +"张票" );
}
}
由于该类实现了Runnable接口,该接口中并没有获取线程方法名称的方法,故只能采用Thread.currentThread().getName()这种最通用的方法来获得正在执行的线程名称。
两种卖票方式的比较:
继承方式:资源不能共享;一共卖出去150张票,每个窗口各50张;由于继承了Thread类之后就不能再继承其他类了;
接口方式:资源共享;一共卖出去50张票;方便以后扩展。
jdk线程的简单使用的更多相关文章
- 自己动手写线程池——向JDK线程池进发
自己动手写线程池--向JDK线程池进发 前言 在前面的文章自己动手写乞丐版线程池中,我们写了一个非常简单的线程池实现,这个只是一个非常简单的实现,在本篇文章当中我们将要实现一个和JDK内部实现的线程池 ...
- jdk线程池ThreadPoolExecutor工作原理解析(自己动手实现线程池)(一)
jdk线程池ThreadPoolExecutor工作原理解析(自己动手实现线程池)(一) 线程池介绍 在日常开发中经常会遇到需要使用其它线程将大量任务异步处理的场景(异步化以及提升系统的吞吐量),而在 ...
- jdk线程池主要原理
本文转自:http://blog.csdn.net/linchengzhi/article/details/7567397 正常创建一个线程的时候,我们是这样的:new thread(Runnable ...
- iOS开发Swift篇(02) NSThread线程相关简单说明
iOS开发Swift篇(02) NSThread线程相关简单说明 一 说明 1)关于多线程部分的理论知识和OC实现,在之前的博文中已经写明,所以这里不再说明. 2)该文仅仅简单讲解NSThread在s ...
- 李洪强iOS开发Swift篇---12_NSThread线程相关简单说明
李洪强iOS开发Swift篇---12_NSThread线程相关简单说明 一 说明 1)关于多线程部分的理论知识和OC实现,在之前的博文中已经写明,所以这里不再说明. 2)该文仅仅简单讲解NSThre ...
- Android系统--输入系统(十一)Reader线程_简单处理
Android系统--输入系统(十一)Reader线程_简单处理 1. 引入 Reader线程主要负责三件事情 获得输入事件 简单处理 上传给Dispatch线程 InputReader.cpp vo ...
- pthread创建线程的简单演示
使用pthread创建子线程的简单步骤 导入头文件 #import <pthread.h> 指定新线程标识符 使用pthread创建线程的函数 根据result = 0 与否判断子线程 ...
- 多线程(三) java中线程的简单使用
java中,启动线程通常是通过Thread或其子类通过调用start()方法启动. 常见使用线程有两种:实现Runnable接口和继承Thread.而继承Thread亦或使用TimerTask其底层依 ...
- JAVA线程及简单同步实现的原理解析
线程 一.内容简介: 本文主要讲述计算机中有关线程的相关内容,以及JAVA中关于线程的基础知识点,为以后的深入学习做铺垫.如果你已经是高手了,那么这篇文章并不适合你. 二.随笔正文: 1.计算机系统组 ...
随机推荐
- IDEA快捷键大全
IntelliJ Idea 常用快捷键列表 Ctrl+Shift + Enter,语句完成“!”,否定完成,输入表达式时按 “!”键Ctrl+E,最近的文件Ctrl+Shift+E,最近更改的文件Sh ...
- Hadoop常见错误解决
1. 通过命令和查看日志文件查看hadoop启动和运行情况 在NameNode端,可以通过 tail -100 /var/log/hadoop/hadoop/hadoop-hadoop-namenod ...
- 多线程编程之Linux环境下的多线程(三)
前面两篇文章都讲述了Linux环境下的多线程编程基础知识,也附带了典型实例.本文主要比较一下Linux环境与Windows环境下的多线程编程区别. 看待技术问题要瞄准其本质,不管是WIN32.Linu ...
- Windows 安装程序无法将 Windows 配置为在此计算机的硬件上运行
遇到这个问题是用辅助工具(WinNTSetup3.exe)进行的安装,重启后就就遇到“Windows 安装程序无法将 Windows 配置为在此计算机的硬件上运行” 解决:在WIN PE 下挂载安装光 ...
- SPOJ #440. The Turtle´s Shortest Path
Coding a Dijkstra is not hard. %70 of my time spent on tackling TLE, as my last post. Dijkstra works ...
- Installing IPython using pip on CentOS
1. First to install pip # wget https://bootstrap.pypa.io/get-pip.py # python get-pip.py 2. Install i ...
- 源码安装extundelete以及对遇到问题的解决
软件下载:http://sourceforge.net/projects/extundelete/ 1.在安装extundelete包./configure时遇到configure: error: C ...
- asp.net中Respons.Write()的用法
很多时候,我们为了是页面的传输速率更高.很自然回去选择脚本和ajax结合进行传值,在传值如要向页面回传数据时,可能只有一次也会是多次.一次的情况下我们可以很好的用Respons.End()方法来截取我 ...
- powerdesigner12.5 设置表字符集和存储引擎
powerdesigner12.5在做建模的时候发现没有找到哪儿设置表的字符集和存储引擎.于是研究了一番. 在菜单上方选择 Database => Edit Current DBMS 然后选 ...
- (WCF) WCF Service Hosting.
3 Options. 1. Host inside of an application. 2. Host into Windows service. 3. Host into IIS 参考: http ...