---------------------- android培训、java培训、期待与您交流! ----------------------
1、什么是进程
进程是指计算机正在运行的程序,一个进程至少有一个线程。
2、什么是线程
线程是一个程序里面不同的执行路径。
main方法本身可以称为主线程。
下面的两个示例可以展示线程的执行过程。
示例1
public class ThreadExer {
//主线程main
public static void main(String[] args) {
Counter counter = new Counter();
//使用线程首先实例化,调用的是构造函数Thread(Runnable targer)。
Thread thread = new Thread(counter);
thread.start(); //线程启动,执行run()方法。
for (int i = 0; i < 100; i++) {
System.out.println("主线程数:" + i);
}
}
}
//执行run()方法有两种,一、实现Runnable接口 二、继承Thread类
public class Counter implements Runnable {
//子线程
public void run() { //run()方法是线程体,准备要实现的功能。
for (int i = 0; i < 100; i++) {
System.out.println("子线程数:" + i);
}
}
}
示例2
与示例1基本相同
//Thread原本已经实现Runnable接口,所以Thread类里也有run()方法
public class Counter extends Thread{
//继承就不用实例化线程 Thread thread=new Thread(Runnable targer);
结果显示:主线程和子线程同时执行,穿插输出。
注:实现Runnable接口,优先于继承Thread类。因为接口拥有更高的扩展性。
2、线程控制基本方法
Thread.sleep(long millis)方法: 将当前线程睡眠指定毫秒数,它是Thread的静态方法,直接用类调用。
抛出中断线程异常:throws InterruptedException(重写的方法不能抛出比被重写方法不同的异常)。
interrupt()中断线程方法(和抛出中断线程异常搭配使用),但此方法比较粗暴,不等线程结束直接中断。其实可以判断run()方法来结束进程,run()方法结束进程就结束。
示例3
import java.util.Date;
public class Counter implements Runnable {// extends Thread{
public void run() {
boolean bool = true;
while (bool) {
System.out.println(new Date());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
bool = false;
}
}
join()方法:合并某个线程
过程:先执行run()方法,然后遇到join()暂停主线程运行,等子线程运行结束会与主线程合并,相当于方法调用。
示例4
//主线程
public class ThreadExer {
public static void main(String[] args) {
Counter counter = new Counter("subThread");
counter.start();//调用run()方法
try {
counter.join();//暂停执行,run()方法执行结束,合并counter,执行主线程
} catch (InterruptedException e) {
}
for (int i = 0; i < 10; i++) {
System.out.println("i am main thread");
}
}
}
//子线程
public class Counter extends Thread{
public Counter() {
}
public Counter(String value) {
super(value);
}
public void run() {
for (int i = 1; i <= 10; i++) {
System.out.println("i am " + getName());
try {
Thread.sleep(1000);//每次停1秒
} catch (InterruptedException e) {
e.getMessage();
}
}
}
}
yield()静态方法:让出CPU,给其他线程执行的机会(只让出一会儿)。
例:
public class ThreadExer{
public static void main(String[] args){
Thread thread1=new Thread(new Counter());
Thread thread2=new Thread(new Counter());
thread1.start();
thread2.start();
}
}
public class Counter implements Runnable{
public void run(){
for(int i=0;i<100;i++){
System.out.println("counter"+i);
if(i%10==0){
Thread.yield();//如果能整除10,就让出一会儿CPU,让另一个线程执行。
}
}
}
}
priority()方法:线程的优先级用数字表示,范围1-10,一个线程默认优先级是5。
例如: Thread.MIN_PRIORITY=1 //最小优先级
Thread.MAX_PRIORITY=10 //最大优先级
Thread.NORM_PRIORITY=5 //默认优先级
设置线程对象优先级
void setPriority(int newPriority);
示例
public class ThreadExer{
public static void main(String[] args){
Thread thread1=new Thread(new Counter1());
Thread thread2=new Thread(new Counter2());
thread1.setPriority(Thread.NORM_PRIORITY+3);//设置线程1,在默认情况下提高3级
thread1.start();
thread2.start();
}
}
public class Counter1 implements Runnable{
public void run(){
for(int i=0;i<100;i++){
System.out.println("counter1"+i);
}
}
}
public class Counter2 implements Runnable{
public void run(){
for(int i=0;i<100;i++){
System.out.println("counter2"+i);
}
}
}
线程同步
synchronized()(锁定当前对象),锁的机制。
通过给对象加“锁”,把当前对象锁定,强化加锁对象的执行完整性。
例:
public class TestSync implements Runnable {// 实现Runnable接口
Timer timer = new Timer();// 生成对象timer
public static void main(String[] args) {
TestSync test = new TestSync();// 实例化本身,生成对象test,同时也实例化Timer类
Thread t1 = new Thread(test);// 实例化线程生成对象t1
Thread t2 = new Thread(test);// 实例化线程生成对象t2,和t1传入的是同一个对象timer
t1.setName("t1");// 设置名字
t2.setName("t2");
t1.start();// 调用run()方法
t2.start();
}
public void run() {
timer.add(Thread.currentThread().getName());// currentThread()当前线程对象
}
}
class Timer {
private static int num = 0;
public synchronized void add(String name) {
// 名字为t1,加锁synchronized之后,当前对象被锁定,此方法为同步方法,t1对象解锁后,t2才执行同步方法。
// synchronized (this) {
num++;//t1:num=1;t2:num=2
try {
Thread.sleep(1);
// t1睡眠1毫秒,暂停t1,执行t2;
// t2睡眠1毫秒,暂停t2,再接着执行t1; t1:num=2;
} catch (InterruptedException e) {
}
System.out.println(name + ", 你是第" + num + "个使用timer的线程");
// }
}
}
结果:未加锁之前,t1和t2都是第2个使用timer的线程。
加锁之后,t1是第1个使用timer的线程,t2是第2个使用timer的线程。
死锁
例:
package thread.exercise;
public class ThreadDeathLock implements Runnable {
public int flag = 1;
static Object o1 = new Object(), o2 = new Object();
public void run() {
System.out.println("flag=" + flag);
if(flag == 1) {
synchronized(o1) {//锁着对象o1
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized(o2) {//只有先解开o2的锁,才能再锁o2
System.out.println("1");
}
}
}
if(flag == 0) {
synchronized(o2) {//锁着对象o2
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized(o1) {//只有先解开o1的锁,才能再锁o1
System.out.println("0");
}
}
}
}
public static void main(String[] args) {
ThreadDeathLock td1 = new ThreadDeathLock();
ThreadDeathLock td2 = new ThreadDeathLock();
td1.flag = 1;
td2.flag = 0;
Thread t1 = new Thread(td1);
Thread t2 = new Thread(td2);
t1.start();
t2.start();
}
}
注:如果一个线程调用同步方法,另一个线程调用非同步方法,就会按照线程流程执行,不会去等待同步方法解锁。
例如:一个写入方法,一个读取方法,写入方法就可以加锁,只能一个对象写入之后,下一个对象才能写入,而多个对象可以 同时读取。
---------------------- android培训、java培训、期待与您交流! ----------------------