进程和线程
进程
进程是正在运行的程序;
是系统进行资源分配和调用的独立单位;
每一个进程都有自己的独立的内存空间和系统资源;
线程
线程是进程中的单个顺序控制流,是一条执行路径;
单线程:一个进程如果只有一个执行路径,则称为单线程;
多线程:一个进程如果有多个执行路径,则称为单线程;
多线程的实现方式:继承Thread类、实现Runnable接口
第一种:继承Thread类;创建测试类使用start方法启动线程
package com.threadtest;
/**
* 继承Thread类
* 实现run方法
*/
public class MyThread extends Thread {
@Override
public void run() {
for (int i =0;i<50;i++){
//getName 获取线程名称
//System.out.println(getName()+":"+i);
//也可以使用Thread.currentThread().getName() 获取线程名称
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
//创建myThread类,启动线程
package com.threadtest;
public class MyThreadDemo {
public static void main(String[] args) {
//创建myThread类,启动线程
MyThread m1=new MyThread();
MyThread m2=new MyThread();
//设置线程名称
m1.setName("线程名称1");
m2.setName("线程名称2");
//仅仅使用run方法是没有启动线程的
/*m1.run();
m2.run();*/
//使用void start() 让线程开始执行,让 java虚拟机调用run方法
m1.start();
m2.start();
}
}
第二种:实现Runnable接口;
//实现Runnable接口
package com.threadtest;
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i =0;i<50;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
//启动线程
package com.threadtest;
public class MyRunnableDemo {
public static void main(String[] args) {
MyRunnable myrunnable = new MyRunnable();
/* Thread t1 = new Thread(myrunnable);
Thread t2 = new Thread(myrunnable);
t1.start();
t2.start();*/
//输出:Thread-1:49 Thread-0:3 ....
Thread t1 = new Thread(myrunnable,"线程名称1");
Thread t2 = new Thread(myrunnable,"线程名称2");
t1.start();;
t2.start();
//输出:线程名称2:49 线程名称1:1 .....
}
}
线程的优先级
getPriority()方法返回线程的优先级;
setPriority()设置线程的优先级;
package com.threadtest;
public class MyThreadDemo {
public static void main(String[] args) {
//创建myThread类,启动线程
MyThread m1=new MyThread();
MyThread m2=new MyThread();
MyThread m3=new MyThread();
//设置线程名称
m1.setName("线程名称1");
m2.setName("线程名称2");
m3.setName("线程名称3");
//getPriority()方法返回线程的优先级
//System.out.println(m1.getPriority()); //5
//System.out.println(m2.getPriority());//5
//System.out.println(m3.getPriority());//5
//System.out.println(Thread.MAX_PRIORITY);//最大优先级 10
//System.out.println(Thread.MIN_PRIORITY);//最小优先级 1
//System.out.println(Thread.NORM_PRIORITY);//默认优先级 5
//setPriority()设置线程的优先级
m1.setPriority(1);//set的值要在最大优先级和最小优先级之间
m2.setPriority(10);
m3.setPriority(5);
//使用void start() 让线程开始执行,让 java虚拟机调用run方法
m1.start();
m2.start();
m3.start();
}
}
线程的控制
sleep(long millis)方法,是当前正在执行的线程停留(暂停执行),指定毫秒数;
join()方法,等待这个线程死亡;
setDaemon(boolean a)方法,将此线程标记为守护线程,当运行的线程都是守护线程的时候,java虚拟机将退出;
package com.threadtest;
public class ThreadSleep extends Thread {
@Override
public void run() {
for (int i =0;i<50;i++){
// System.out.println(getName()+":"+i);
System.out.println(Thread.currentThread().getName()+":"+i);
try {
//休眠一秒钟执行一次
ThreadSleep.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.threadtest;
public class ThreadSleepDemo {
public static void main(String[] args) {
ThreadSleep t1 = new ThreadSleep();
ThreadSleep t2 = new ThreadSleep();
ThreadSleep t3 = new ThreadSleep();
t1.setName("张三");
t2.setName("李四");
t3.setName("王五");
//设置一个主线程
Thread.currentThread().setName("主线程");
//设置守护线程之后,主线程结束了 t1 t2 t3将都不再执行
t1.setDaemon(true);
t2.setDaemon(true);
t3.setDaemon(true);
t1.start();
try {
//等t1执行完之后(死亡)才会执行 t2 t3
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
t3.start();
for (int i=0;i<6;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
线程的生命周期
数据安全锁(例子:卖票)
卖票例子如以下代码块:
package com.threadtest;
public class SellTicket implements Runnable {
private int tickets=100;
//解决相同票出现多次的情况需要用synchronized锁,声明一个对象,保证每个线程公用一把锁
private Object obj = new Object();
/**
* 卖票方法第一种,使用synchronized锁对象
*/
@Override
public void run() {
while (true){
//避免相同票出现了多次,为代码块上锁
synchronized (obj){
//synchronized锁可以解决数据安全问题,但是线程很多的时候,
//每个线程都会去判断同步锁,很耗费资源,降低了程序运行效率
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(tickets>0) {
System.out.println(Thread.currentThread().getName()+"卖出了一张票,买的是第"+tickets+"张");
tickets--;
} *//*else {
System.out.println(Thread.currentThread().getName()+"被询问,票已经卖完了");
}*//*
}
}
}
/**
* 卖票方法第二种,使用synchronized关键字加载方法上
*/
public void run() {
while (true){
sell();
}
}
//synchronized关键字加载方法上,就可以实现同步
private synchronized void sell() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(tickets>0) {
System.out.println(Thread.currentThread().getName()+"卖出了一张票,买的是第"+tickets+"张");
tickets--;
}
}
/**
* 第三种 使用lock锁
*/
private Lock lock =new ReentrantLock();
@Override
public void run() {
while (true){
try {
lock.lock();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(tickets>0) {
System.out.println(Thread.currentThread().getName()+"卖出了一张票,买的是第"+tickets+"张");
tickets--;
}
} finally {
lock.unlock();
}
}
}
}
//开启抢票线程
package com.threadtest;
public class SellTicketDemo {
public static void main(String[] args) {
SellTicket s1 = new SellTicket();
Thread t1 = new Thread(s1);
Thread t2 = new Thread(s1);
Thread t3 = new Thread(s1);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}