线程和进程之间的区别
1.进程是资源分配的最小单位,线程是cpu调度的最小单位,一个进程包含多个线程
2.线程不能看做独立应用,而进程可以看做独立应用
3.进程有独立的地址空间,相互不影响,线程只是进程中的不同执行路径
线程没有独立的地址空间
继承Thread
public class MyThread extends Thread{
/*
* 利用继承中的特点
* 将线程名称传递 进行设置
*/
public MyThread(String name){
super(name);
}
/*
* 重写run方法
* 定义线程要执行的代码
*/
public void run(){
for (int i = 0; i < 20; i++) {
System.out.println(getName()+i);
}
}
}
public class Demo {
public static void main(String[] args) {
System.out.println("这里是main线程");
MyThread mt = new MyThread("小强");
mt.start();//开启了一个新的线程
for (int i = 0; i < 20; i++) {
System.out.println("旺财:"+i);
}
}
}
实现Runable接口
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
public class Demo {
public static void main(String[] args) {
//创建自定义类对象 线程任务对象
MyRunnable mr = new MyRunnable();
//创建线程对象
Thread t = new Thread(mr, "小强");
t.start();
for (int i = 0; i < 20; i++) {
System.out.println("旺财 " + i);
}
}
}
Thread 和Runnable的区别
- 适合多个相同的程序代码的线程去共享同一个资源。
- 可以避免java中的单继承的局限性。
- 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。
- 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类
- 扩展.:java命令执行一个类的时候,实际上都会启动一个JVM,每一个JVM其实在就是在操作系统中启动了一个进
程
实现callable接口
ThreadLocal
同部代码块
synchronized(同步锁){
需要同步操作的代码
}
同部方法锁
public synchronized void method(){
可能会产生线程安全问题的代码
}
lock锁
- java.util.concurrent.locks.Lock 机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作,
同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。
Lock锁也称同步锁,加锁与释放锁方法化了,如下:
Lock的子类ReentrantLock
- public void lock() :加同步锁。
- public void unlock() :释放同步锁
public class Ticket implements Runnable{
private int ticket = 100;
Lock lock = new ReentrantLock();
/*
* 执行卖票操作
*/
@Override
public void run() {
//每个窗口卖票的操作
//窗口 永远开启
while(true){
lock.lock();
if(ticket>0){//有票 可以卖
//出票操作
//使用sleep模拟一下出票时间
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//获取当前线程对象的名字
String name = Thread.currentThread().getName();
System.out.println(name+"正在卖:"+ticket‐‐);
} finally{ //无论程序是否发生异常都释放锁
lock.unlock();
}
}
}
线程状态的概述
线程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(new runable());
线程池
newCachedThreadPool(通常是首选)
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造
的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。
newFixedThreadPool
创建一个可重用固定线程数的线程池,一次性预先执行代价高昂的线程分配,限制线程的数量,这样可以节省时间,因为你不用为每个人物都固定的付出创建线程的开销
newSingleThreadExecutor
Executor.ThreadExecutor()返回一个线程池(这个线程池只有一个线程),这个线程池可以在线程死后(或发生异常时)重新启动一个线程来替代原来的线程继续执行下去!
Java 里面线程池的顶级接口是 Executor,但是严格意义上讲 Executor 并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是 ExecutorService。
有返回值线程池
实现Callable接口而不是Runnble接口,在java se5中引入的callable是一种具有参数的泛型,它的类型参数表示的是从方法call()中固定返回值,并且必须使用ExecutorService.submit()方法调用它
(详情见java编程思想658页)