线程:程序执行过程中并发执行的代码段,属于同一个进程,内存共享
进程:进程之间的内存是隔离的,不同进程通信通过socket套接字
线程创建方式一:
继承Thread类
1.子类覆盖父类中的run方法,将线程运行的代码存放在run中
2.建立子类对象的同时线程也被创建
3.通过调用start方法开启线程
线程类Thread包含的方法:
1.start():通知CPU可以开始执行该线程
2.run():线程具体执行的代码
class MyThread extends Thread{
public void run(){
System.out.println("run----------");
}
}
public class ThreadDemo {
public static void main(String[] args) {
MyThread M=new MyThread();
M.start();
//创建匿名内部类
new Thread(){
public void run(){
System.out.println("up--------");
}
}.start();
}
}
3.getName():获取线程名称
class MyThread extends Thread{
public void run(){
System.out.println("run----------");
}
}
public class ThreadDemo {
public static void main(String[] args) {
MyThread M=new MyThread();
M.start();
System.out.println(M.getName());
//创建匿名内部类
Thread T=new Thread(){
public void run(){
System.out.println("up--------");
}
};
T.start();
System.out.println(T.getName());
}
}
得到当前线程:
System.out.print(Thread.currentThread().getName());
4.yield():暂停当前正在执行的线程对象,并执行其他线程。
5.sleep(int ms):(静态方法,可通过类名直接调用)让线程休眠指定的毫秒数
由于sleep()的执行有可能抛出异常,所以将sleep()的方法调用放在try-catch块中
class MyThread1 extends Thread{
public void run(){
while(true){
System.out.println(getName());
try{
sleep(100);
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
public class ThreadSleep {
public static void main(String[] args) {
MyThread1 m1=new MyThread1();
m1.start();
MyThread1 m2=new MyThread1();
m2.start();
}
}
6.join():等待该线程终止
class Player extends Thread{
private String name;
private int seconds;
public Player(String name,int seconds){
this.name=name;
this.seconds=seconds;
}
public void run(){
try{
System.out.println("玩家" + name +"出发了");
sleep(seconds*1000);
System.out.println("玩家" + name +"到达了,花了" + seconds + "秒");
}
catch(Exception e){
e.getStackTrace();
}
}
}
public class ThreadSleep1 {
public static void main(String[] args) throws InterruptedException {
Player p1=new Player("成龙",2);
Player p2=new Player("李连杰",3);
Player p3=new Player("甄子丹",4);
Player p4=new Player("赵文卓",2);
p1.start();
p2.start();
p3.start();
p4.start();
p1.join();
p2.join();
p3.join();
p4.join();
System.out.println("可以开局了!");
}
}
7.setDaemon(true) 设置守护线程,守护进程中的所有线程,当其他所有线程结束,此守护线程结束,在线程启动前设置
8.setPriority(intnumber) 设置线程优先级
同步代码块
synchronized(Object){ }
在同步块中只允许一个线程访问共享资源
class Saler extends Thread{
private String name;
private static int tickets=100;
private static Object lock=new Object(); //要用static修饰,保证不同对象用的是一个锁
public Saler(String name){
this.name=name;
}
public void run(){
while(true){
synchronized(lock){
if(tickets>0){
int tmp = tickets;
try{
Thread.sleep(10);
}
catch(Exception e){
}
tickets =tmp-1;
System.out.println(name + ":" + tmp);
}
}
yield();
}
}
}
public class ThreadSale {
public static void main(String[] args) {
Saler s1=new Saler("张三");
Saler s2=new Saler("李四");
Saler s3=new Saler("王五");
s1.start();
s2.start();
s3.start();
}
}
同步方法:
在方法前面加修饰关键字synchronized 如:public synchronized void DoIt(){}
当某个对象调用了同步方法时,在对象当中保证这个方法只能同时被一个线程访问。
生产者消费者问题:
notify():唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性 的,并在对实现做出决定时发生。线程通过调用其中一个 wait
方法,在对象的监视器上等待。
wait()
package workpackage;
public class Bee extends Thread{
private int bag = 0;
private static final int BAG_MAX = 20;
private static final int ONCE = 5; //每生产5斤可放入蜜罐
private static final int TIME = 10; //生产一斤花费10ms
private Box box; //蜜罐子
private String name;
public Bee(String name,Box box){
this.name = name;
this.box = box;
}
public void run(){
while(true){
//满足放蜂蜜的条件
if(bag >= ONCE){
//向蜜罐放蜂蜜
synchronized(box){
//取出当前蜜罐容量
int cap = box.capacity;
if(cap >= Box.MAX){
box.notifyAll(); //通知熊吃蜜
}
//未满
else{
//蜜罐剩余的空间
int remain = Box.MAX-cap;
//蜜蜂袋
if(bag >= remain){
box.capacity = Box.MAX;
bag = bag - remain;
System.out.println(name + ".添加了" + remain + ",name.bag=" + bag + ",蜜罐有" + box.capacity);
box.notifyAll(); //通知熊吃蜜
}
//不足remain
else{
box.capacity = box.capacity + bag;
System.out.println(name + ".添加了" + bag + ",name.bag=" + bag + ",蜜罐有" + box.capacity);
bag = 0;
}
}
}
}
//向小包增加蜂蜜
if(bag >= Bee.BAG_MAX){
synchronized(box){
try {
box.wait();
}
catch (Exception e) {
}
}
}
else{
bag++;
System.out.println(name + ".bag=" + bag);
try {
Thread.sleep(TIME);
}
catch(Exception e){
}
}
}
}
}
package workpackage;
//蜜罐子
public class Box {
public static final int MAX = 30;
public int capacity = 0;
}
package workpackage;
public class Bear extends Thread{
private Box box;
private String name;
//构造函数
public Bear(Box box,String name){
this.box=box;
this.name=name;
}
public void run(){
while(true){
synchronized (box) {
if(box.capacity == Box.MAX ){
System.out.println(name + "吃掉了" + box.capacity );
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
box.capacity = 0;
box.notifyAll();
}
else{
try {
box.wait();
} catch (Exception e) {
}
}
}
}
}
}
package workpackage;
public class App {
public static void main(String[] args) {
Box box = new Box(); //蜜罐
Bee bee1 = new Bee("b-1", box);
Bee bee2 = new Bee("b-2", box);
Bee bee3 = new Bee("b-3", box);
Bee bee4 = new Bee("b-4", box);
Bee bee5 = new Bee("b-5", box);
Bee bee6 = new Bee("b-6", box);
Bee bee7 = new Bee("b-7", box);
Bee bee8 = new Bee("b-8", box);
Bee bee9 = new Bee("b-9", box);
Bee bee10 = new Bee("b-10", box);
Bear bear1 = new Bear(box,"熊大");
Bear bear2 = new Bear(box,"熊二");
bee1.start();
bee2.start();
bee3.start();
bee4.start();
bee5.start();
bee6.start();
bee7.start();
bee8.start();
bee9.start();
bee10.start();
bear1.start();
bear2.start();
}
}
wait()和sleep()的区别:
wait()释放CPU执行权,释放锁
sleep()释放CPU执行权,不释放锁
线程创建方式二:
实现Runnable接口
由于java不支持多次继承,如果程序需要继承其他非Thread类,而且还要实现多线程,就可通过Runnable接口来实现。Runnable接口只有一个run()方法。
Thread类中有两个构造函数:
1.public Thread(Runnable target)
2.public Thread(Runnable target,String name)
这两个构造方法的参数中都存在Runnable实例,这样就可以将Runnable实现与Thread实例相关联。
实现Runnable接口
1.子类覆盖接口中的run方法;
2.通过Thread类创建线程,并将实现了Runnable接口的子类对象作为参数传递给Thread类的构造函数;
3.Thread类对象调用start()方法开启线程;
class Vehicle{
private String name;
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
}
class Car extends Vehicle implements Runnable{
public void run(){
System.out.println(getName());
}
}
public class RunnableDemo {
public static void main(String[] args) {
Car c1=new Car();
c1.setName("BMW");
Car c2=new Car();
c2.setName("BZ");
Thread t1=new Thread(c1);
Thread t2=new Thread(c2);
t1.start();
t2.start();
}
}