多线程的创建方式:
Java语言允许程序同时进行多个线程,主要通过java.lang.Thread类来体现。
方式一:
继承于Thread类,步骤:1.创建一个继承于Thread类的子类;2.重写Thread中的run()方法;3.创建Thread类的子类对象;4.通过此对象调用start()方法
不能通过run()
public class ThreadTest {
public static void main(String[] args) {
PrimeThread p = new PrimeThread();
p.start();
}
}
class PrimeThread extends Thread{
public void run(){
for(int i = 1;i < 100;i++){
if(i%2==0){
System.out.println(i);
}
}
}
}
窗口买票实例
class Window extends Thread{
private static int ticket = 100;
@Override
public void run() {
while (true){
if(ticket >0) {
System.out.println(getName() + "票号为:" + ticket);
ticket--;
}else {
break;
}
}
}
}
public class ThreadMethodTest {
public static void main(String[] args) {
Window w1 = new Window();
Window w2 = new Window();
Window w3 = new Window();
w1.setName("窗口一");
w2.setName("窗口二");
w3.setName("窗口三");
w1.start();
w2.start();
w3.start();
}
}
方式二:
通过实现Runnable
步骤:1.创建一个实现了Runnable的类;2.实现类的抽象方法run();3.创建实现类对象;4.将此对象作为参数传递到Thread的构造方法,创建Thread对象;5.通过Thread对象调用start()方法
class MyThread implements Runnable{
@Override
public void run() {
for(int i = 0; i < 100;i++){
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + i);
}
}
}
}
public class ThreadTest2 {
public static void main(String[] args) {
MyThread m1 = new MyThread();
Thread t1 = new Thread(m1);
t1.start();
}
}
窗口买票实例
class RunTest implements Runnable{
private int ticket = 100;
@Override
public void run() {
while(true){
if(ticket>0){
System.out.println(Thread.currentThread().getName() + ", " + ticket);
ticket--;
}else{
break;
}
}
}
}
public class RunnableTest {
public static void main(String[] args) {
RunTest r1 = new RunTest();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r1);
Thread t3 = new Thread(r1);
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
t1.start();
t2.start();
t3.start();
}
}
方式三:实现Callable接口
步骤:1创建类实现Callable接口;2.重写call函数,将此线程需要执行的写在这个函数中;3.创建Callable接口实现类对象;4.将此Callable接口实现类对象作为参数传递到FutureTask构造器中,创建FutureTask类对象;5.将FutureTask对象作为参数传递到Thread构造器中作为参数,创建Thread类对象,开启线程
class NumThread implements Callable{
@Override
public Object call()throws Exception {
int sum = 0;
for(int i = 0;i < 100;i++){
if(i % 2 == 0){
System.out.println(i);
sum += i;
}
}
return sum;
}
}
public class CallableTest {
public static void main(String[] args) {
NumThread numthread = new NumThread();
FutureTask futureTask = new FutureTask(numthread);
new Thread(futureTask).start();
try {
Object sum = futureTask.get();
System.out.println(sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
方式四:使用线程池
class RunThread implements Runnable{
@Override
public void run() {
for(int i = 0;i < 100;i++){
if(i % 2 == 0){
System.out.println(i);
}
}
}
}
class CallThread implements Callable{
@Override
public Object call() throws Exception{
int sum = 0;
for(int i = 0;i<100;i++){
if(i % 2 == 1){
System.out.println(i);
sum += i;
}
}
return sum;
}
}
public class ThreadPoor {
public static void main(String[] args) {
//提供指定数量的线程池
ExecutorService service= Executors.newFixedThreadPool(10);
service.execute(new RunThread());//适用于Runnable
service.submit(new CallThread());//适用于Callable
service.shutdown();//关闭线程池
}
}
线程的常用方法:
void start():启动线程,并调用run()方法
vodi run():线程在被调度时执行的操作
String getName():返回线程的名称
void setName():设置线程的名称
static Thread currentThread():返回当前的线程
static Thread yield():释放当前CPU的执行权
join() :在线程A中插入线程B的jion方法,此时A进入阻塞状态,直到B结束后,继续执行线程A
stop():强制结束当前线程的生命(已过时,不推荐使用)
sleep(long millitimes):当前线程睡眠millitimes毫秒
bool isAlive():判断线程是否还活着
线程的优先级:
MAX_PRIORITY:最高级 10级
MIN_PRIORITY:最低级 1级
NORM_PRIORITY:默认优先级 5级
获取当前线程优先级 getPriority()
设置当前线程优先级 setPriority
线程的几种状态:
同步机制:
1)同步代码块
synchronized(同步监视器){
//需要被同步的代码块
}
同步的代码块:操作共享数据的代码
共享数据:多个线程共同操作的变量
同步监视器:任何一个类的对象,且所有的共用一个监视器(在实现runnable接口中,可以考虑使用this充当)
class RunTest implements Runnable{
private int ticket = 100;
Object obj = new Object();
@Override
public void run() {
while(true) {
synchronized (obj){//同步代码块
if(ticket > 0){
try {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + "," + ticket);
ticket--;
}catch (Exception e){
e.printStackTrace();
}
}else{
break;
}
}
}
}
}
public class RunnableTest {
public static void main(String[] args) {
RunTest r1 = new RunTest();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r1);
Thread t3 = new Thread(r1);
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
t1.start();
t2.start();
t3.start();
}
}
2)同步方法
如果共享数据全部包含在一个方法中,我们不妨把这个方法弄成同步方法
同步方法的监视器是不需要我们显示调用的,在非静态情况下,默认为this
class RunTest implements Runnable{
private int ticket = 100;
@Override
public void run() {
while(true) {
show();
}
}
public synchronized void show(){//将此方法定义为同步方法
if(ticket > 0){
try {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + "," + ticket);
ticket--;
}catch (Exception e){
e.printStackTrace();
}
}
}
}
public class RunnableTest {
public static void main(String[] args) {
RunTest r1 = new RunTest();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r1);
Thread t3 = new Thread(r1);
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
t1.start();
t2.start();
t3.start();
}
}
用Lock来写同步方法
public class LockTest {
public static void main(String[] args) {
Window t = new Window();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
t1.setName("窗口1");
t2.setName("窗口1");
t3.setName("窗口1");
t1.start();
t2.start();
t3.start();
}
}
class Window implements Runnable{
private int ticket = 100;
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true){
try {
lock.lock();
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "," + ticket);
ticket--;
} else {
break;
}
}finally {
lock.unlock();
}
}
}
}