多线程

几乎所有的操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序就是一个进程。当一个程序运行时,内部可能包含了一个或多个顺序执行流,每个数序执行流就是一个线程。
线程和进程
几乎所有的操作系统都支持进程的概念,所有运行中的任务通常对应一个进程(Process)。当一个程序进入内存运行时,即变成一个进程。进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位。进程是内存资源分配的最小单位,切换开销比较大。
线程是进程的组成部分,一个进程可以拥有多个线程,一个线程必须有一个父进程。线程可以拥有自己的堆栈,自己的程序计数器和自己的局部变量,但不拥有系统资源,它与父进程其他的线程共享该进程所拥有的全部资源。因为多个线程共享父进程里的全部资源,因此变成更加方便;但必须更加小心,因为需要确保线程不会妨碍同一进程里的其他线程。
线程可以完成一定的任务,可以与其他线程共享父进程中的共享变量以及部分环境,相互之间协同来完成进程所需要的任务。
线程是独立运行的,它并不知道进程中是否还有其他线程存在。线程的执行是抢占式的,也就是说,当前运行的线程在任何时候都可能被挂起,以便另外一个线程可以运行。
一个线程可以创建和撤销另一个线程,同一个进程中的多个线程可以并发执行。

线程的创建和启动

Java中使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用都是完成一定的任务,实际上就是执行一段程序流(一段数序执行的代码)。java使用线程执行体来代表这段程序流。
继承Thread类创建线程类

public class ThreadTest	extends Thread{//继承父类Thread
	public void run(){//重写run方法
		for(int i = 0 ; i <= 100; i++){
			System.out.println(getName()+""+i);
		}
	}
	public static void main(String[] args){
		ThreadTest ts = new ThreadTest();
		ts.start();//调用线程对象的start()方法来启动线程
		for(int i = 0 ; i <= 100; i++){
			System.out.println("我爱编程");
		}	
	}
}

实现Runnable接口创建线程类
定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的体同样是该线程的线程之行体
创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
调用线程对象的start()方法来启动该线程。

public class ThreadTest	implements Runnable{//继承父类Thread
	public void run(){//重写run方法
		for(int i = 0 ; i <= 100; i++){
			System.out.println(Thread.currentThread.getName()+""+i);
		}
	}
	public static void main(String[] args){
		ThreadTest ts = new ThreadTest();
		Thread th = new Thread(ts);//创建Thread对象
		th.start();//调用线程对象的start()方法来启动线程
		for(int i = 0 ; i <= 100; i++){
			System.out.println("我爱编程");
		}	
	}
}

建议 使用后Runnable创建线程
使用Callable和Future创建线程
使用call()方法的好处是:
call()方法可以有返回值.
call()方法可以声明抛出异常


import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Call implements Callable<Integer> {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		Call c = new Call();
		//创建执行服务
		ExecutorService service = Executors.newFixedThreadPool(1);
		//提交执行
		Future<Integer> f = service.submit(c);//submit这里是提交
		//得到结果
		Integer a = f.get();
		System.out.println(a);
		//关闭服务
		service.shutdown();
	}
	@Override
	public Integer call() throws Exception {//call方法
		return 1;//返回值
	}
}

线程的生命周期
新生 :刚创建 new()
就绪:start() / submit()
运行
阻塞:线程调用了sleep()方法;
线程调用了一个阻塞式的IO方法,在该方法返回之前,该线程被阻塞。
终止:正常执行完。
控制线程
join():让一个线程等待另一个线程执行完成

public class ThreadTest	implements Runnable{//继承父类Thread
	public void run(){//重写run方法
		for(int i = 0 ; i <= 100; i++){
			System.out.println(Thread.currentThread.getName()+""+i);
		}
	}
	public static void main(String[] args){
		
		for(int i = 0 ; i < 100; i++){
			System.out.println("我爱编程");
			if(i==20){
				ThreadTest ts = new ThreadTest();
				Thread th = new Thread(ts,"join的线程");//创建Thread对象
				th.start();//调用线程对象的start()方法来启动线程
				th.join();
			}
		}	
	}
}

sleep():线程睡眠:抱着资源睡觉
yield():暂定当前线程,但不会阻塞当前线程,只是将该线程转入就绪状态。
改变程序的优先级
MAX_PRIORITY:10
MIN_PRIORITY:1
NORM_PRIORITY:5
setPriority(int newPriority):Thread提供的方法来设置优先级
getPriority():得到优先级
线程安全问题
同步代码块:

public class ThreadTest implements Runnable {// 继承父类Thread
	Tickets tickets = new Tickets();
	public void run() {// 重写run方法
		while (true) {
			if (tickets.tickets <= 0) {
				break;
			}
			try {
				Thread.sleep(50); // 线程睡眠50ms
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			synchronized (tickets) {
				if (tickets.tickets <= 0) {//双重判断
					break;
				}
				System.out.println(Thread.currentThread().getName() + "买到第:" + tickets.tickets-- + "张票");

			}
		}
	}

	public static void main(String[] args) {
		ThreadTest ts = new ThreadTest();
		new Thread(ts, "张三").start();
		new Thread(ts, "李四").start();
		new Thread(ts, "王五").start();
	}
}

class Tickets {
	int tickets = 100;
}

同步方法:

public class ThreadTest implements Runnable {// 继承父类Thread
	int tickets=100;
	public synchronized void run() {// 重写run方法
		while (true) {
			if (tickets <= 0) {
				break;
			}
			try {
				Thread.sleep(50); // 线程睡眠50ms
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
				System.out.println(Thread.currentThread().getName() + "买到第:" + tickets-- + "张票");
		}
	}

	public static void main(String[] args) {
		ThreadTest ts = new ThreadTest();
		new Thread(ts, "张三").start();
		new Thread(ts, "李四").start();
		new Thread(ts, "王五").start();
	}
}

synchronized关键字可以修饰方法,代码块但是不能修饰构造器,成员变量等。同步方法由于范围过大执行效率较慢,同步块可以做到恰当的大小(不至于过大或者过小)效率相对来说比较高

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值