#JAVA多线程的简介
- 通过学习本文档后能够掌握到的知识点
- 1、什么是线程
- 2、JAVA中如何实现多线程
- 3、线程的生命周期
- 4 、线程的基本方法
子曰:“学而不思则罔,思而不学则殆。”
###1. 线程
计算机中有几个比较重要的概念:程序、进程、和线程。
程序:一个静态的,一个解决某种问题的指令集合。一个程序在运行的时候可以产生几个进程。
进程:进程是操作系统一个相对独立的单元,是程序的一次执行!进程是有生命周期的。一个进程可以看作是一个程序,但是一个程序可以包含好几个进程。
线程:线程是CPU真正处理的一块。一个线程可以是一个进程,但是一个进程是一个或多个线程的集合。
在JAVA中一个APPLICATION程序中,MAIN()方法就是代表一个主线程。
2.JAVA多线程
JAVA的多线程是其语言的特色之一,多线程指的是同时完成多个任务。但是实际上,并不是CPU同时在处理几个任务!CPU处理线程是通过分配时间片来进行的,哪个线程抢到了时间片CPU就执行哪个线程。并且当代的计算机CPU处理速度极快,而执行一个线程的时间并不需要多久,多个线程同时存在,争夺使用CPU的时间片。在几毫秒的时间中便完成了所有的计算,因此造成了人们以为CPU在同时执行多个任务。
当然,如果你的电脑有多个CPU那便是真正的多线程了!JAVA中的多线程实现是通过JAVA.LANG.THREAD类来实现的。通常使用两种方法来进行线程的创建继承THREAD类,以及实现RUNNABLE接口。
实际上JAVA中的线程是基于JVM虚拟的CPU而实现的。不论是继承THREAD类,还是实现RUNNABLE接口都需要进行重写RUN方法,RUN方法实际上是线程需要执行的任务。并且所有的线程都应该使用**START()**方法来开启!
多线程的数据与内存都是共享的。
3. 简单的DEMO
如何实现了线程得创建!使用Thread类进行创建
//使用继承Thread类来创建线程
public class test01{
public static void main(String [] args){
//创建线程
System.out.println("主线程开始");
Thread t1 = new thread();
//线程的启动都是通过start 开始 的 .
t1.start();
for(int i = 0 ; i <=100 ; i++){
System.out.print("主线程"+i);
}
}
}
//创建线程类
class thread extends Thread{
//重写RUN方法
public void run(){
//进行循环测试
for(int i = 0; i < 10 ; i++){
System.out.print("子线程"+i);
}
}
}
基于RUNNABLE方法实现多线程。
package chapter01;
import java.text.SimpleDateFormat;
import java.util.Date;
//此类,用于测试多线程。尽量使用
public class TestManyThread {
public static void main(String[] args) {
try{
int a = 3;
}finally {}
Thread t1 = new Thread(new Runner(1));
Thread t2 = new Thread(new Runner(2));
Thread t3 = new Thread(new Runner(3));
Thread t4 = new Thread(new Runner(4));
Thread t5 = new Thread(new Runner(5));
Thread t6 = new Thread(new Runner(6));
Thread t7 = new Thread(new Runner(7));
Thread t8 = new Thread(new timer());
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
t8.start();
}
}
class Runner implements Runnable{
private int id;
public Runner(int i) {
this.id=i;
}
//重写run方法,为代码快
public void run () {
for(int i = 0 ; i< 10 ;i++) {
System.out.println("id:"+id+"no"+i);
}
}
}
class timer implements Runnable{
public void run() {
while(true) {
System.out.println(new SimpleDateFormat().format(new Date()));
//让他睡一会
try {//1000毫秒为一秒
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
4. 线程的生命周期
一般来说线程的生命分为
创建阶段、就绪阶段、执行阶段、阻塞阶段和结束阶段
当进行start()方法被调用的时候线程就被创建了。此时线程等待cpu的时间片,等待的时候称之为就绪状态,被分到了CPU的时间片就开始运行。CPU执行线程的时候就是执行状态。如果你的线程如果级别高、亦或者被锁住(Synchronized),无人争抢时间片,那么当它执行完以后就直接终止。但是事实上大部分会被阻塞!正如我上文所说,当代CPU并不是真的同时在处理几个任务!在每个时间片上只有一个线程是被执行的,其他的线程就处于阻塞的状态。一个线程有优先级之分。1到10,越大的优先级越高!在无认为干扰的情况下,CPU会根据线程的优先级来进行时间片的分配。但是人是可以干预的!比如wait()方法,当你在线程中调用了wait()方法,那此线程就将会等待notify()的唤醒。如果你得程序一直在抢资源让别的线程等待,那将会出现死锁的问题!
##5.控制线程的优先级以及暂停线程
1.如何设置线程的优先级
线程的优先的是通过线程的类方法进行设置的。
package chapter01;
//此类用来测试线程的优先级
public class TestThreadFirst {
public static void main(String[] args) {
//创建新的线程
Thread t1 = new Thread(new myThread02());
t1.setName("liwei");
t1.start();
t1.setPriority(Thread.MAX_PRIORITY);
for(int i = 0 ; i< 10 ; i++) {
System.out.println("这是主线程 === "+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class myThread02 implements Runnable{
@Override
public void run() {
for(int i = 0 ; i< 10 ; i++) {
System.out.println("这是子线程"+this.getClass().getName()+" === "+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
t1.setPriority(Thread.MAX_PRIORITY);通过这个方法可以实现设置优先级。但是这个效果一般般!
join()方法和sleep()方法能够暂停线程得执行。线程中设定join()以后能够展停其他进程的执行。sleep方法就是睡,让线程睡一会。
package chapter01;
//此方法是用来测试
public class TestJoinMethod {
public static void main(String[] args) {
//父类new子类:原理是什么?上溯造型为的是是系统更加容易扩展,和理解
Thread t1 = new task2();
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i = 0 ; i < 10 ; i++) {
System.out.println(i+10);
}
}
}
//尽量使用runable接口,而不是继承。因为单继承太限制了。Thread继承了runable接口
class task2 extends Thread{
//重写run方法 。
public void run() {
//用来测试Join方法
for(int i = 0 ; i < 10 ; i++) {
System.out.println(i);
//睡一会更加能体现
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
###6. 定时任务
一般来说定时任务,你就可以直接写个线程让他睡睡到固定的时候就起来工作。不过JAVA中提供了一个叫做TIMER的方法,可以通过这个来执行。
package chapter01;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
//此类用来测试timer方法
public class TestTimer2 {
public static void main(String[] args) {
Timer t1 = new Timer();
TimerTask t2 = new myTask2();
//t2,代表的是任务,第一个1000是代表第一次执行的间隔时间,第二个时间代表的是以后每次间隔多久跑一次
t1.schedule(t2, 1000,1000);
}
}
class myTask2 extends TimerTask{
@Override
public void run() {
// TODO Auto-generated method stub
//这是用来做定时任务的代码点。
System.out.println("这里是定时任务"+new SimpleDateFormat().format(new Date()));
}
}
##7.设置后台程序
GC,垃圾回收线程就是后台线程,优先级是很低的!java中通过设置Thread t = new Thread(); t.setDaemon(true);方法来设定后台程序。
package chapter01;
import java.util.Date;
/**
* 此类用于测试DAEMON类型后台线程
* @author HAND_WEILI
*
*/
public class TestThreadDaemon {
public static void main(String[] args) {
Thread t1 = new MyThread();
t1.setDaemon(true);
t1.start();
for(int i = 0 ; i < 10 ; i++) {
System.out.println("main"+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class MyThread extends Thread{
public void run() {
//重写run方法
for(int i = 0;i < 10 ; i++) {
System.out.println(i+"This kid Thread"+new Date());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}