JAVA笔记14-线程
一、概念
线程:是一个程序里面不同的执行路径,每一个分支都叫线程。到现在为止我们所讲的程序分支只有一个,即main方法,称作主线程。
进程:class文件,exe文件。程序的执行过程:程序放入代码区(进程产生,准备开始执行,进程是静态的概念),平时所说的“进程的执行”是指进程中主线程(main)的执行,实际运行得都是线程。
Windows Linux Unix操作系统是支持多进程、多线程的,Dos是只支持单进程的。一个时间点上一个cpu只有一个线程在执行,CPU很快,看起来像是同时运行。真正的多线程:多个CPU,双核。
二、线程的产生方式
Java的线程是通过java.lang.Thread类实现的。可以通过创建Thread的实例来创建新的线程。通过调用Thread类的start()方法来启动一个线程。VM启动时会有一个由主方法所定义的线程。每个线程都是通过某个特定Thread对象所对应的run()方法来完成其操作的,run()方法称为线程体。
可以有两种方式创建新的线程:
方法一:(建议使用此法)
(1)定义线程类实现Runnable接口
(2)Thread myThread = new Thread(target)//target为Runnable接口类型
(3)Runnable中只有一个方法:public void run();//用以定义线程运行体
(4)使用Runnable接口可以为多个线程提供共享的数据
(5)在实现Runnable接口的类的run方法定义中可以使用Thread的静态方法:public static Thread currentThread()//获得当前线程的引用
方法一举例:要new Thread对象来调用start方法启动线程,之后产生分支,主线程和分支线程并行执行;但是如果直接调用run方法,就是方法调用,还是单线程。
public class TestThread1{
public static void main(String args[]){
Runner1 r = new Runner1();
Thread t = new Thread(r);
t.start();//不可以直接用r.start();或r.run()
for(int i=0; i<100; i++){
System.out.println("Main Thread:---------------------"+i);
}
}
}
class Runner1 implements Runnable{
public void run(){
for(int i=0; i<100; i++){
System.out.println("Runner1:"+i);
}
}
}
方法二:
(1)可以定义一个Thread的子类并重写其run方法。如:class MyThread extends Thread{public void run(){……}}
(2)然后生成该类的对象:MyThread myThread = new MyThread(……)
方法二举例:
public class TestThread1{
public static void main(String args[]){
Runner1 r = new Runner1();
r.start();//可以直接用r.start();但不可以r.run()
for(int i=0; i<100; i++){
System.out.println("Main Thread:---------------------"+i);
}
}
}
class Runner1 extends Thread{
public void run(){
for(int i=0; i<100; i++){
System.out.println("Runner1:"+i);
}
}
}
三、线程状态转换
start之后进入“就绪”,等待cpu时间片,时间片到达后进入“运行”,阻塞事件发生(如IO),事件解决则进入“就绪”

线程控制的基本方法:

注:就绪,运行,阻塞属于“活着”。优先级高,则分配的时间多。
1、sleep方法:使得当前线程休眠(暂时停止执行millis毫秒)
可以调用Thread的静态方法:public static void sleep(long millis) throws InterruptedException,因为抛异常所以必须要写try catch。
由于是静态方法,所以可以由类名直接调用Thread.sleep(…);
sleep方法举例:在哪个线程调用sleep就是让这个线程睡眠,如第7行的sleep方法是让主线程睡眠。而第10行是主线程睡眠10000ms后,来打断睡眠1000ms中的MyThread线程,导致该子线程抛异常。catch到异常后,该子线程结束。
import java.util.*;//因为是用Date()
public class TestInterrupt{
public static void main(String args[]){
MyThread thread = new MyThread();
thread.start();
try{
Thread.sleep(10000);
}catch(InterruptedException e){
}
thread.interrupt();//Interrupt不是让子线程结束的好方法。stop更不好,尽量也不要使用
}
}
class MyThread extends Thread{
public void run(){
while(true){
System.out.println("==="+new Date()+"===");
try{
sleep(1000);
}catch(InterruptedException e){
return;
}
}
}
}
输出:
===Mon Apr 21 17:16:28 CST 2014===
===Mon Apr 21 17:16:29 CST 2014===
===Mon Apr 21 17:16:30 CST 2014===
===Mon Apr 21 17:16:31 CST 2014===
===Mon Apr 21 17:16:32 CST 2014===
===Mon Apr 21 17:16:33 CST 2014===
===Mon Apr 21 17:16:34 CST 2014===
===Mon Apr 21 17:16:35 CST 2014===
===Mon Apr 21 17:16:36 CST 2014===
===Mon Apr 21 17:16:37 CST 2014===
注意:Interrupt不是让子线程结束的好方法。stop更不好,尽量也不要使用,建议这样:控制flag使run方法结束,run方法结束则线程结束。
import java.util.*;//因为是用Date()
public class TestInterrupt{
public static void main(String args[]){
MyThread thread = new MyThread();
thread.start();
try{
Thread.sleep(10000);
}catch(InterruptedException e){
}
thread.shutDown();
}
}
class MyThread extends Thread{
private boolean flag = true ;
public void run(){
while(flag==true){
System.out.println("==="+new Date()+"===");
try{
sleep(1000);
}catch(InterruptedException e){
return;
}
}
}
public void shutDown(){
flag = false;
}
}
注意:重写的方法不能比父类抛出不同的异常,所以不能在run方法抛出异常。
2、join方法:合并某个线程
join方法举例:第7行,join是合并两个线程,相当于方法调用。程序先执行子线程,主线程再执行。
import java.util.*;//因为是用Date()
public class TestJoin{
public static void main(String args[]){
MyThread t = new MyThread("abcde");
t.start();
try{
t.join();
}catch(InterruptedException e){
}
for(int i=1; i<=10; i++){
System.out.println("I am main thread----"+i);
}
}
} class MyThread extends Thread{
MyThread(String s){
super(s);
}
public void run(){
for(int i=1; i<=10; i++){
System.out.println("I am "+getName()+"==="+i);
try{
sleep(1000);
}catch(InterruptedException e){
return;
}
}
}
}
输出:
I am abcde===1
I am abcde===2
I am abcde===3
I am abcde===4
I am abcde===5
I am abcde===6
I am abcde===7
I am abcde===8
I am abcde===9
I am abcde===10
I am main thread----1
I am main thread----2
I am main thread----3
I am main thread----4
I am main thread----5
I am main thread----6
I am main thread----7
I am main thread----8
I am main thread----9
I am main thread----10
3、yield方法:让出CPU,给其他线程执行的机会
yeild方法举例:下面程序有三条路径(main,t1,t2),每次到10的倍数则让出cpu。不经常用。
public class TestYeild{
public static void main(String args[]){
MyThread t1 = new MyThread("t1");
MyThread t2 = new MyThread("t2");
t1.start();
t2.start();
}
}
class MyThread extends Thread{
MyThread(String s){
super(s);
}
public void run(){
for(int i=1; i<=100; i++){
System.out.println("I am "+getName()+"==="+i);
if(i%10==0){
yield();
}
}
}
}
四、线程优先级(优先级高得到的cpu执行的时间片多)
Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。线程调度器按照线程的优先级决定应调度哪个线程来执行。线程的优先级用数字表示,优先级范围1~10,默认是5。
Thread.MIN_PRIORITY = 1
Thread.MAX_PRIORITY = 10
Thread.NORM_PRIORITY = 5
使用下述方法获得或设置线程对象的优先级:
int getPriority();
void setPriority(int newPriority);
举例:t1的优先级高于t2,但并非等到t1执行完毕后t2才执行。
public class TestPriority{
public static void main(String args[]){
Thread t1 = new Thread(new T1());
Thread t2 = new Thread(new T2());
t1.setPriority(Thread.NORM_PRIORITY+3);
t1.start();
t2.start();
}
}
class T1 implements Runnable{
public void run(){
for(int i=1; i<=100; i++){
System.out.println("T1:"+i);
}
}
}
class T2 implements Runnable{
public void run(){
for(int i=1; i<=100; i++){
System.out.println("--------T2:"+i);
}
}
}
i<=1000时的部分输出:

四、其他例子
1、同一个线程对象,用来启动两个线程
public class Test{
public static void main(String args[]){
Runner r = new Runner();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
t2.start();
}
}
class Runner implements Runnable{
public void run(){
for(int i=0; i<30; i++){
System.out.println("No."+i);
}
}
}
2、currentThread是当前线程(this是当前对象)
public class Test{
public static void main(String args[]){
Thread t = new Runner();
t.start();
for(int i=0; i<30; i++){
System.out.println("MainThread:"+i);
}
}
}
class Runner extends Thread{
public void run(){
System.out.println(Thread.currentThread().isAlive());
for(int i=0; i<30; i++){
System.out.println("SubThread:"+i);
}
}
}
JAVA笔记14-线程的更多相关文章
- java笔记--使用线程池优化多线程编程
使用线程池优化多线程编程 认识线程池 在Java中,所有的对象都是需要通过new操作符来创建的,如果创建大量短生命周期的对象,将会使得整个程序的性能非常的低下.这种时候就需要用到了池的技术,比如数据库 ...
- java笔记--守护线程的应用
守护线程的应用 Java中的线程可以分为两类,即用户线程和守护线程.用户线程是为了完成任务,而守护线程是为其他线程服务 --如果朋友您想转载本文章请注明转载地址"http://www.cnb ...
- java笔记--关于线程同步(7种同步方式)
关于线程同步(7种方式) --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3897440.html"谢谢-- 为何要使用同步? ...
- java笔记--关于线程通信
关于线程通信 使用多线程编程的一个重要原因就是线程间通信的代价比较小 --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3897773.h ...
- java笔记--关于线程同步(5种同步方式)【转】
为何要使用同步? java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完 ...
- java 笔记(5) —— 线程,yield,join
一.线程各个状态与转换: 新建状态:用new语句创建的线程对象处于新建状态,此时它和其它的java对象一样,仅仅在堆中被分配了内存 .就绪状态:当一个线程创建了以后,其他的线程调用了它的start() ...
- java笔记--关于线程同步(5种同步方式)
转自:http://www.2cto.com/kf/201408/324061.html 为何要使用同步? java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改 ...
- java笔记之线程方式1启动线程
* 需求:我们要实现多线程的程序. * 如何实现呢? * 由于线程是依赖进程而存在的,所以我们应该先创建一个进程出来. * 而进程是由系统创建的,所以我们应该去调用系统功能创建一个进程. * ...
- java笔记之线程简述1
1:线程是依赖于进程而存在. 2:什么是进程? 通过任务管理器我们就看到了进程的存在. 而通过观察,我们发现只有运行的程序才会出现进程. 进程:就是正在运行的程序. 进程是系统进行资源分配和调 ...
- Thinking in Java——笔记(14)
Type Information The need for RTTI Because it is a dynamically bound method, the proper behavior wil ...
随机推荐
- 正确关闭selinux
.查看当前selinux的状态命令为 getenforce .两个都要关.注意先看看有么有这两个文件,如果没有就创建一个,否则后期会出现很多问题 cat > /etc/selinux/confi ...
- Dojo入门:初识Dojo
Dojo的全称是Dojo Toolkit,始创于2004年,是当前各种蓬勃发展的JS工具包中的佼佼者.Dojo 为富互联网应用程序(RIA) 的开发提供了完整的端到端的解决方案,包括核心的 Jav ...
- 【VS开发】 自己编写一个简单的ActiveX控件——详尽教程
最近开始学ActiveX控件编程,上手不太容易,上网想找相关教程也没合适的,最后还是在师哥的指导下完成了第一个简单控件的开发,现在把开发过程贴出来与大家分享一下~ (环境说明--平台:vs2005:语 ...
- python 并发编程 多线程 线程queue
线程queue 线程之间已经是共享数据的,为什么还使用线程queue? 线程需要自己加锁,线程queue帮我们处理好加锁的问题 有三种不同的用法 第一种方法: class queue.Queue(ma ...
- 7大python 深度学习框架的描述及优缺点绍
Theano https://github.com/Theano/Theano 描述: Theano 是一个python库, 允许你定义, 优化并且有效地评估涉及到多维数组的数学表达式. 它与GPUs ...
- Luogu P2915 [USACO08NOV]奶牛混合起来
题外话: 是非常颓废的博主 写题解也不在于能不能通过啦,主要是缓解颓废 首先看到这个题,肯定是可以暴力搜索的: 不得不说这道题还是很善良的,一波大暴力dfs,居然有70pts: #include< ...
- 原生js:click和onclick本质的区别(转https://www.cnblogs.com/web1/p/6555662.html)
原生javascript的click在w3c里边的阐述是DOM button对象,也是html DOM click() 方法,可模拟在按钮上的一次鼠标单击. button 对象代表 HTML 文档中的 ...
- NEO4J亿级数据导入导出以及数据更新
1.添加配置 apoc.export.file.enabled=true apoc.import.file.enabled=true dbms.directories.import=import db ...
- mycat 笔记
Mycat读写分离.主从切换.分库分表的操作记录 系统开发中,数据库是非常重要的一个点.除了程序的本身的优化,如:SQL语句优化.代码优化,数据库的处理本身优化也是非常重要的.主从.热备.分表分库 ...
- 异步分布式队列Celery
异步分布式队列Celery 转载地址 Celery 是什么? 官网 Celery 是一个由 Python 编写的简单.灵活.可靠的用来处理大量信息的分布式系统,它同时提供操作和维护分布式系统所需的工具 ...