首先了解一些基本知识
线程
线程,有时被称为轻量进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。
线程是程序中一个单一的顺序控制流程。进程内有一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指令运行时的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。
进程
狭义定义:进程就是程序的执行过程。
进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
进程的概念主要有两点:第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体,我们称其为进程。
进程是操作系统中最基本、重要的概念。是多道程序系统出现后,为了刻画系统内部出现的动态情况,描述系统内部各道程序的活动规律引进的一个概念,所有多道程序设计操作系统都建立在进程的基础上。
进入正题
一.线程的创建方式
方式一:继承Thread并重写run方法
package thread;
/**
* 线程有两种创建方式:
* 方式一:继承Thread并重写run方法,并在run方法中添加线程要执行的任务代码。
* 1:由于java继承是单继承的,这就导致了继承了Thread就不能继承其它类,在实际开发中有诸多不便。
* 2:定义线程的同时在run方法中定义了线程要执行的任务,这就导致了线程和执行的任务有一个必然的耦合关系,不利于线程的重用。
* @author soft01
*
*/
public class ThreadDemo01 {
public static void main(String[]args) {
Thread t1=new MyThread1();
Thread t2=new MyThread2();
Thread t3=new MyThread3();
/**
* 需要注意,启动线程要调度的是线程的start方法,而不是直接调用run方法
* 当start方法调用之后,线程纳入线程调度,一旦线程获取cpu时间片段后,线程会自动调用run方法
*
*/
t1.start();//线程没有先后顺序,是调度器随机调度的
t2.start();//start()方法启动线程
t3.start();
}
}
/**
* 线程和线程执行的任务存在强 耦合 关系;扩展性不好,不灵活,重复性差
*/
class MyThread1 extends Thread{
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("劫");
}
}
}
class MyThread2 extends Thread{
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("均衡存乎万物之间");
}
}
}
class MyThread3 extends Thread{
public void run() {
for(int i=0;i<100;i++) {
System.out.println("传统是智慧的糟粕");
}
}
}
方式二:实现Runnable接口单独定义
package thread;
/**
* 第二种创建线程的方式:
* 实现Runnable接口单独定义 线程任务
* 这样 线程和 线程内的方法就解 耦合 了;线程就可以继承别的类
* @author soft01
*
*/
public class ThreadDemo02 {
public static void main(String[] args) {
//实例化线程任务
Runnable r1=new MyRunnable1();
Runnable r2=new MyRunnable2();
//实例化线程
Thread t1=new Thread(r1);
Thread t2=new Thread(r2);
t1.start(); //线程没有先后,而是随机的
t2.start();
t1.yield();
}
}
class MyRunnable1 implements Runnable{
public void run() {
for(int i=0;i<100;i++) {
System.out.println("摇摇晃晃");
}
}
}
class MyRunnable2 implements Runnable{
public void run() {
for(int i=0;i<100;i++) {
System.out.println("摇还是不摇");
}
}
}
附加小点心:匿名内部类创建线程
package thread;
/**
* 使用匿名内部类的创建形式完成线程的两种方式创建
* @author soft01
*
*/
public class ThreadDemo03 {
public static void main(String[] args) {
//继承Thread重写run方法:
Thread t1=new Thread() {
public void run() {
for(int i=0;i<100;i++) {
System.out.println("诺克萨斯");
}
}
}; //加;号,匿名内部类,这是一行语句
//实现Runnable接口:
Runnable r2=new Runnable() {
public void run() {
for(int i=0;i<100;i++) {
System.out.println("比尔");
}
}
};
Thread t2=new Thread(r2);
t1.start();
t2.start();
}
}
二.线程的信息
package thread;
public class Thread_info {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread main=Thread.currentThread();
//获取线程名字
String name=main.getName();
System.out.println("name:"+name);
//获取线程唯一标识
long id=main.getId();
System.out.println("id:"+id);
//获取线程的优先级
int priority=main.getPriority();
System.out.println("priority:"+priority);
//是否处于活动状态
boolean isAlive=main.isAlive();
System.out.println("isAlive:"+isAlive);
//是否为守护线程
boolean isDaemon=main.isDaemon();
System.out.println("isDaemon:"+isDaemon);
//中断
boolean isInterrupted=main.isInterrupted(); //正常中断就是false 强制中断就是true
System.out.println("isInterrput:"+isInterrupted);
//中断线程 void
main.interrupt();
}
}
三.线程的优先级
package thread;
/***
*线程的优先级
*线程的并发运行是靠线程调度统一的,线程不能主动获取CPU时间段,也不能决定时间片段的长短,只能被动地被分配。
*通过调整线程的优先级别可以最大程度地改善获取CPU时间片的几率。
*理论上 线程优先级别越高的线程,获取CPU时间片的次数越多,线程的优先级由一个int值表示,范围是1到10,
*1为最低优先级,10为最高优先级,5为默认值。
* @author soft01
*
*/
public class Thread_setPriority {
public static void main(String[]args) {
Thread min=new Thread() {
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("德玛西亚万岁");
}
}
};
Thread max=new Thread() {
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("诺克萨斯万岁");
}
}
};
Thread norm=new Thread() {
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("均衡教派万岁");
}
}
};
norm.setPriority(Thread.NORM_PRIORITY);
max.setPriority(Thread.MAX_PRIORITY);
min.setPriority(Thread.MIN_PRIORITY);
norm.start();
min.start();
max.start();
}
}
class MyThread01 extends Thread{
}
class MyThread02 extends Thread{
}
class MyThread03 extends Thread{
}
四.Thread.currentThread();
package thread;
/**
* 线程提供了一个静态方法:
* static Thread currentThread()
* 该方法可以获取运行这个方法的线程
*
* 获取线程状态信息的
* @author soft01
*
*/
public class Thread_currentThread {
public static void main(String[] args) {//其实main方法就是一个线程运行的
// TODO Auto-generated method stub
Thread t0=Thread.currentThread();
System.out.println("运行该该方法的线程是:"+t0);
//main线程开始执行dosome方法
dosome();
//自定义线程
Thread t=new Thread("可以起线程名字") {
public void run() {
Thread t=Thread.currentThread();
System.out.println("运行run方法的线程是自定义线程:"+t);
dosome();
}
};
t.start();
//自定义线程2
Thread t1=new MyThread();
Thread.currentThread();
System.out.println("运行自定义线程2中run方法的线程是"+t1);
}
public static void dosome() {
Thread t=Thread.currentThread();
System.out.println("运行dosome方法的线程是:"+t);
}
}
class MyThread extends Thread{
public void run() {
System.out.println("nihao");
}
}
五.线程的其他方法
package thread;
/**
* Thread的静态方法yield
* 该方法用于使当前线程主动让出当此CPU时间片段回到Runnable状态,等待分配时间片段
* @author soft01
*
*/
public class Thread_yield {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t1=new Thread() {
public void run() {
for(int i=0;i<500;i++) {
try {
System.out.println("泰拉瑞亚"+i);
Thread.sleep(1000);
yield();
}catch(Exception e) {
e.printStackTrace();
}
}
}
};
Thread t2=new Thread() {
public void run() {
for(int i=0;i<500;i++) {
try {
System.out.println("鬼泣5 "+i);
Thread.sleep(10);
// yield();
}catch(Exception e) {
e.printStackTrace();
}
}
}
};
t1.start();
t2.start();
}
}
/**
* Thread 的静态方法join
* 该方法用于等待当前线程结束。 需要结束的线程.join();
* 该方法声明抛出 InterruptException
* @author soft01
* 打断,等待线程
*
*/
/**
* 线程1:生成一百个随即数
* 线程2:负责排序(等待线程1的结束)
* @param args
*/
package thread;
import java.util.Arrays;
import java.util.Random;
public class Thread_join01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
/**
* 两个线程共享同一个数组,t1负责生成随机数,t2负责排序,t2要等待t1的结束再继续排序
*/
int[] ary=new int[100];
Thread t1=new ThreadA(ary);
Thread t2=new ThreadB(ary,t1);
t1.start();
t2.start();
}
}
//生成随机数的线程
class ThreadA extends Thread{
int[]ary;
public ThreadA(int[]ary) {
this.ary=ary;
}
public void run() {
Random r=new Random();
for(int i=0;i<100;i++) {
ary[i]=r.nextInt(100);
}
//输出数组中的全部数据
System.out.println(Arrays.toString(ary));
}
}
//排序线程
class ThreadB extends Thread{
int[]ary;
Thread t1;
public ThreadB(int[]ary,Thread t1) {
this.ary=ary;
this.t1=t1;
}
public void run() {
//等待t1的结束 那就要先获得t1的引用
try {
System.out.println("等待t1的结束!");
//等待t1结束
t1.join();
//t1正常结束,可以排序了
Arrays.sort(ary);
System.out.println(Arrays.toString(ary));
}catch(Exception e) {
//等待t1结束期间,被其他线程打断,提前结束等待
e.printStackTrace();
}
}
}
package thread;
/**
* Thread提供了一个静态方法:
* static void sleep(long ms)
* 该方法允许运行这个方法的线程进入阻塞状态指定毫秒超时后线程会自动回到Runnable状态等待继续并发运行。
*
* 通常使用sleep方法控制周期性执行任务(如:定时器)
* 可以确保阻塞时间长,但是不能精确的时间间隔,因为sleep结束之后,是进入了Runnable状态,等待cpu分配时间,而未进入running状态
* @author soft01
*
*/
public class Thread_sleep {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("程序开始了!");
try {
Thread.sleep(5000);
}catch(InterruptedException e) {//线程阻塞中,被中断,会抛出异常;若未阻塞,中断线程,则不会抛出异常
e.printStackTrace();
}
System.out.println("程序结束了!");
}
}
六.守护线程
package thread;
/**
* 守护线程演示
*
* 守护线程在全部前台线程结束后被结束,
* 不是立即结束,而是有少许延迟
* 理论:java进程在全部前台线程结束时结束。
* 如果java线程没有结束的话,则说明存在一个以上的没有结束的前台线程正在运行。
* @author soft01
*
*/
public class Thread_Daemon {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t1=new Thread1();
Thread t2=new Thread2();
//将t2线程设置为守护线程
t2.setDaemon(true);
//启动线程
t1.start();
t2.start();
}
}
/**
* 前台线程
* @author soft01
*
*/
class Thread1 extends Thread{
public void run() {
for(int i=0;i<100;i++) {
System.out.println("前台:"+i);
try {
Thread.sleep(10);
}catch(Exception e) {
e.printStackTrace();
}
}
System.out.println("前台结束");
}
}
class Thread2 extends Thread{
public void run() {
for(int i=0;i<500;i++) {
System.out.println("后台:"+i);
try {
Thread.sleep(10);
}catch(Exception e) {
e.printStackTrace();
}
}
System.out.println("后台结束");
}
}
package thread;
//在内部类中运用守护线程
public class Thread_Daemon02 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t=new Thread() {
public void run() {
for(int i=0;i<10;i++) {
System.out.println("中国!");
try {
Thread.sleep(1000);
}catch(Exception e) {
e.printStackTrace();
}
}
}
};
t.setDaemon(true);
}
}